c - 如何读取C中的输入

标签 c scanf

我正在尝试使用 scanf("%[^\n]"); 读取一行就在它之前,我正在读取一个带有“%d”的整数,有人告诉我 scanf 在读取后不会删除 '\n',所以我必须调用 fflush() 来避免它,但即使这样做我仍然有同样的问题,所以这是我的代码:

scanf("%d", &n);
fflush(stdin);

lines = (char**)malloc(sizeof(char*)*n);

for(i = 0; i < n; i++){
    lines[i] = (char*)malloc(sizeof(char)*1001);
}

for(i = 0;i < n;i++){
    scanf("%[^\n]", linhes[i]);
}

我读取一个整数,然后 scanf 不会等待,它开始读取输入 - 无论整数值是多少,无论是 5 还是 10,scanf 都会将所有字符串读取为空。已经尝试使用 fgets,结果几乎相同,只是它读取一些字符串并跳过其他字符串。

最佳答案

让我们一步一步来看:

"... read a line with scanf("%[^\n]");".

scanf("%[^\n]", buf) 不读取一行。几乎确实如此——有时。 "%[^\n]" 指示 scanf() 读取任意数量的非 '\n' char 直到遇到一个('\n' 然后被放回 stdin)或发生 EOF。

这种方法有一些问题:

  1. 如果第一个 char'\n',则 scanf() 将其放回 stdin,而无需无论如何改变buf! buf 保持原样 - 也许未初始化scanf() 然后返回 0。
  2. 如果至少读取一个非'\n',则将其保存到 buf 和更多 char 中,直到发生 出现“\n”'\0' 被附加到 buf 中,'\n' 被放回 stdinscanf() 返回 1。这种无限性很容易溢出 buf。如果没有保存char并且发生EOF或输入错误,scanf()返回EOF
  3. 始终检查 scanf()/fgets() 等函数的返回值。如果您的代码没有检查它,则 buf 的状态未知。

无论如何,'\n' 通常仍保留在 stdin 中,因此 未完全读取。此'\n' 通常是next 输入函数的问题。

... scanf doesn't erase the '\n' after reading

另一个常见的误解。 scanf() 读取或不读取 '\n',具体取决于提供的格式。某些格式使用 '\n',其他格式则不使用。

... call fflush() to avoid it

fflush(stdin) 在某些编译器中定义良好,但不在 C 标准中。通常的问题是代码想要消除 stdin 中的任何剩余数据。当行尾尚未发生时,一种常见的替代方法是读取并处理,直到找到 '\n':

int ch;  // Use int
while ((ch = fgetc(stdin)) != '\n' && ch != EOF);

I still have the same problems

在我看来,最好的解决方案是读取一行用户输入,然后扫描它。

char buf[sizeof lines[i]];
if (fgets(buf, sizeof buf, stdin) == NULL) return NoMoreInput();

// If desired, remove a _potential_ trailing \n
buf[strcspn(buf, "\n")] = 0;

strcpy(lines[i], buf);

我建议缓冲区的大小应约为典型代码预期输入大小的 2 倍。健壮的代码(而不是此片段)将检测是否需要读取更多行。 IMO,这种过长的线路通常是黑客的迹象,而不是合法使用。

关于c - 如何读取C中的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30881102/

相关文章:

c - sscanf 坏了吗?

c - C 中的 fscanf 带有一个没有空格的文本文件

c - 如何使 .txt 文件对 Visual C 可见

c++ - 通过sscanf解析字符串

c - 是否有任何平台在 fd_set 上使用结构副本(对于 select() 或 pselect())会导致问题?

c - 无法对 C 程序使用 readlink for/proc/self/exe

c - 用c代码制作凯撒密码?

我可以计算 scanf 的参数数量吗?

c - 从输入中读取具有定义字符数的字符串

c - 指针变量的大小