【问题标题】:Reading input input into a char pointer with scanf使用 scanf 将输入输入读入 char 指针
【发布时间】:2021-08-17 18:06:13
【问题描述】:

我想在这里做的是,我想用 scanf 将用户的输入读入 char 指针,并在读取更多输入时动态分配内存。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *ptr, temp;
    int i, ind = 0;

    ptr = malloc(sizeof(char) * 2);

    while (scanf(" %[^\n]c", &temp) != EOF)
    {
        ptr[ind] = temp;
        ind++;
        ptr = realloc(ptr, sizeof(char) * (ind + 1));
    }

    for (i = 0; i < 5; i++)
        printf("%c", *(ptr + i));

    return 0;
}

我的代码是这样的,但是它要么引发分段错误(当一行中的字符数超过 8 个时),要么甚至不打印任何字符。我错过了什么?提前致谢。

【问题讨论】:

  • 2 * sizeof(char) 并没有完全按照你的想法做,你只为 2 个字符分配内存。
  • @alex01011:他们就是这么想的。它们以两个字符开头,并使用realloc 来读取更多字符。
  • @EricPostpischil 那么scanf() 是错误的函数:)
  • 至少是那种形式
  • 这就是 scanf 的 m 标志的用途:scanf("% m[^\n]", &amp;ptr);

标签: c scanf dynamic-memory-allocation


【解决方案1】:

除了 Eric 的回答之外,如果没有 scanf(),您的代码可能会更好。这是getchar() 解决方案:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int c = 0; /* int so it can hold the EOF value */
    size_t ind = 0, i = 0;
    char *buff = NULL, *tmp = NULL;

    buff = malloc(2); /* sizeof char is 1 */

    if (buff == NULL) /* malloc failed */
    {
        exit(EXIT_FAILURE);
    }

    while (1)
    {
        c = getchar();

        if (c == EOF || c == '\n')
        {
            break;
        }

        buff[ind++] = (char)c; /* maybe check for overflow here, for non ascii characters */

        /* can use ctype functions or just manually compare with CHAR_MIN and CHAR_MAX */

        tmp = realloc(buff, ind + 2);

        if (tmp == NULL) /* reallloc failed */
        {
            fprintf(stderr,"Out of memory\n");
            exit(EXIT_FAILURE);
        }

        buff = tmp;
    }

    /* --------- NULL terminate if you are looking for a string  */

    /* buff[ind] = 0;                                            */

    /* --------------------------------------------------------- */

    for (; i < ind; i++)
    {
        putchar(*(buff + i));
    }

    free(buff);

    return 0;
}

我想补充一下,多次调用realloc() 并不是一个足够的做法。更好的方法是,最初使用 malloc() 分配 X 数量的内存,如果您需要更多,然后使用具有适当大小的 realloc()

【讨论】:

  • realloc的结果赋值给与输入参数相同的指针是错误的。有很多比我知识渊博的人,建议不要使用realloc;而是调用malloc,测试它是否成功,释放你正在使用的那个,然后用最近的malloc返回的新值覆盖它
  • buff = realloc(buff, ind + 2); 当(不是如果)realloc() 失败时,您用NULL 覆盖由buff 持有的地址,从而丢失您的原始指针地址,从而造成内存泄漏。始终使用临时指针 realloc(),例如void *tmp = realloc(buff, ind + 2); if (!tmp) { perror ("realloc-buff"); /* handle error */ } buff = tmp;
  • 我使用了 realloc 因为输入的大小未知,我被告知要使用它。但是您的解决方案就像魅力一样。非常感谢:)
  • @GeorgeMiddletown 他们指出的是正确的。我更新了答案。谢谢大佬!
【解决方案2】:

scanf(" %[^\n]c", &amp;temp) 不会读取不是换行符 ('\n') 的字符。 [ 本身就是一个转换说明符,c 不附带它。

%[^\n] 表示读取任意数量的字符,直到看到换行为止。 c 不是转换的一部分,它的存在会导致 scanf 中的匹配失败。

要读取一个不是换行符的字符,请使用%1[^\n],如scanf(" %1[^\n]", &amp;temp);

另一种解决方案是:

  • 在 scanf 中使用 %c。之后,测试该字符,如果是换行符则忽略它。
  • 将代码更改为使用getchar 而不是scanf

避免使用scanf(...) != EOF 进行测试。 scanf 仅在第一次转换完成之前发生输入故障时才返回 EOF。否则,它返回分配的输入项数。这可能适用于 scanf 的简单用途,只需分配一项。但是,通常,您至少要测试scanf 是否分配了所需的项目数scanf(...) == 1。更好的办法是保存返回值并处理多个可能的返回:EOF,一个小于所需项目数的数字,或所需的项目数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 2015-04-06
    • 2015-05-30
    相关资源
    最近更新 更多