使用scanf()从键盘读取时从上一个输入读取换行符

这应该是非常简单的,但是我无法从键盘读取连续的输入。

这是代码:

#include  #include  int main() { char string[200]; char character; printf ("write something: "); scanf ("%s", string); printf ("%s", string); printf ("\nwrite a character: "); scanf ("%c", &character); printf ("\nCharacter %c Correspondent number: %d\n", character, character); return 0; } 

怎么了

当我输入一个字符串(例如:计算机)时,程序会读取换行符( '\n' )并将其置于character 。 以下是显示的外观:

  write something: computer computer Character: Correspondent number: 10 

此外,该程序不适用于包含多个单词的字符串。 我怎么能克服这些问题?

第一个scanf读取输入的字符串并在输入缓冲区中留下\n 。 下一次调用scanf读取\n并将其存储到character
试试这个

 scanf (" %c", &characte); // ^A space before %c in scanf can skip any number of white space characters. 

程序不适用于多个字符串的字符串,因为一旦找到空格字符, scanf停止读取。 你可以改用fgets

  fgets(string, 200, stdin); 

OP的第一个问题通常是通过在格式前加一个空格来解决。 这将占用空白区域,包括前一行的'\n'

 // scanf("%c", &character); scanf(" %c", &character); 

此外,该程序不适用于包含多个单词的字符串。 我怎么能克服这些问题?

对于第二个问题,让我们更准确地理解“字符串”以及"%s"作用。

字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。 7.1.1 1

即使报告“我输入一个字符串(例如:计算机)”,OP也没有输入字符串。 OP正在输入一行文字。 8个字符“computer”,然后按Enter键 。 这里没有“空字符”。 而是9个char "computer\n"

scanf("%s", string); 做3件事:

1)扫描,但不保存任何前导空白区域。

2)扫描并保存为string任意数量的非空白区域。

3)到达白色空间或EOF时停止扫描。 那个char只能回到stdinstring附加'\0' ,使char数组成为C 字符串

要读取包含空格的行,请不要使用scanf("%s",...考虑fgets()

 fgets(string, sizeof string, stdin); // remove potential trailing \r\n as needed string[strcspn(string, "\n")] = 0; 

混合scanf()fgets()是一个问题,像scanf("%s", string); fgets(...)这样的调用scanf("%s", string); fgets(...) scanf("%s", string); fgets(...)stdin保留'\n' ,以便fgets()读取为仅包含"\n" 。 建议使用fgets() (或* nix系统上的getline()读取所有用户输入。 然后解析读取的行。

 fgets(string, sizeof string, stdin); scanf(string, "%c", &character); 

如果代码必须使用scanf()来读取包含空格的用户输入:

 scanf("%*[\n]"); // read any number of \n and not save. // Read up to 199 `char`, none of which are \n if (scanf("%199[^\n]", string) != 1) Handle_EOF(); 

最后,代码应该使用错误检查和输入宽度限制。 测试所有输入函数的返回值。

您所看到的是您调用的函数的正确行为:

  • scanf将从输入中读取一个字,并在输入的字后立即保留输入指针。 如果键入computercomputer读取的下一个字符是换行符。

  • 要读取整行,包括最终换行符,请使用fgets 。 仔细阅读文档: fgets返回一个字符串,其中包含它读取的最终换行符。 ( gets ,由于多种原因不应该使用,读取并丢弃最终换行符。)

我应该补充一点,虽然scanf有其用途,但是我认为你发现,交互使用它会导致非常混乱的行为。 即使在您想要逐字阅读的情况下,如果预期用途是交互式的,也可以使用其他方法。

你可以使用%*c

 #include  #include  int main() { char string[200]; char character; printf ("write something: "); scanf ("%s%*c", string); printf ("%s", string); printf ("\nwrite a character: "); scanf ("%c%*c", &character); printf ("\nCharacter %c Correspondent number: %d\n", character, character); return 0; } 

%*c将接受并忽略换行符或任何空格

你也可以在scanf行之后放入getchar() 。 它会做的工作:)

流需要刷新。 执行连续输入时,标准输入流stdin缓冲键盘上的每次按键。 因此,当您键入“计算机”并按下回车键时,输入流也会吸收换行,即使只将字符串“computer”分配给string 。 因此,当您稍后扫描某个字符时,已加载的新行字符是扫描并分配给character

还需要刷新stdout流。 考虑一下:

 ... printf("foo"); while(1) {} ... 

如果尝试执行类似这样的操作,则控制台上不会显示任何内容。 系统缓冲了stdout流,标准输出流,没有意识到接下来会遇到无限循环的事实,一旦发生这种情况,它就永远不会有机会将流卸载到控制台。

显然,每当scanf阻塞程序并等待stdin (标准输入流)时,它以类似的方式影响其他缓冲流。 无论如何,无论如何,如果事情开始笨拙,最好能够正确地冲洗流。

对代码的以下修改似乎产生了所需的输出

 #include  #include  int main() { char string[200]; char character; printf ("write something: "); fflush(stdout); scanf ("%s", string); fflush(stdin); printf ("%s", string); printf ("\nwrite a character: "); fflush(stdout); scanf ("%c", &character); printf ("\nCharacter %c Correspondent number: %d\n", character, character); return 0; } 

输出
写点东西:电脑
电脑
写一个字符:a

字符对应号码:97