我有以下程序:
int main(int argc, char *argv[])
{
int a, b;
char c1, c2;
printf("Enter something: ");
scanf("%d",&a); // line 1
printf("Enter other something: ");
scanf("%d", &b); // line 2
printf("Enter a char: ");
scanf("%c",&c1); // line 3
printf("Enter another char: ");
scanf("%c", &c2); // line 4
printf("Done"); // line 5
system("PAUSE");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
正如我在C书中读到的那样,作者说scanf()在缓冲区中留下了一个新的行字符,因此,程序不会在第4行停止供用户输入数据,而是将新行字符存储在c2中并移至第5行.
是对的吗?
但是,这只发生在char数据类型中吗?因为我没有int在第1,2,3行中看到数据类型的这个问题.是不是?
Jer*_*ock 62
该scanf()函数在尝试解析字符以外的转换之前会自动删除空格.字符格式(主要是%c;也是扫描集%[…]- 和%n)是例外; 他们不删除空格.
使用" %c"前导空白跳过可选空格.不要在scanf()格式字符串中使用尾随空白.
请注意,这仍然不会消耗输入流中留下的任何尾随空格,甚至不会消耗到行尾,因此请注意,如果也使用getchar()或fgets()在同一输入流上.我们只是让scanf 在转换之前跳过空格,就像它%d和其他非字符转换一样.
请注意,除了转换之外的非空白"指令"(使用POSIX scanf术语),如文字文本scanf("order = %d", &order);也不会跳过空格.文字order必须匹配要读取的下一个字符.
所以你可能想要" order = %d"在那里跳过前一行的换行但仍然需要在固定字符串上进行文字匹配,就像这个问题一样.
ilk*_*chu 11
为了呼应我在另一个关于 C++ 的答案中发布的内容:我建议扔掉scanf(),永远不要使用它,而是使用fgets()and sscanf()。
原因是,至少在默认情况下类 Unix 系统中,运行 CLI 程序的终端会在程序看到用户输入之前对用户输入进行一些处理。它会缓冲输入,直到输入换行符,并允许进行一些基本的行编辑,例如使退格键起作用。
因此,您永远无法一次获得一个字符,或者几个单个字符,而只是一整行。但这不是egscanf("%d")处理的内容,而是仅处理数字,然后停在那里,将其余部分缓冲在C 库中,以供将来的stdio函数使用。如果你的程序有例如
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
Run Code Online (Sandbox Code Playgroud)
当你输入 line 时,它会同时123 abcd完成两个s ,但只有在给出换行符之后才会完成。 scanf()当用户点击空格时,第一个scanf()不会返回,即使这是数字结束的地方(因为此时该行仍在终端的行缓冲区中);第二个scanf()不会等待您输入另一行(因为输入缓冲区已经包含足够的内容来填充转换%s)。
这不是用户通常所期望的!
相反,他们期望按回车键完成输入,如果你按回车键,你要么得到一个默认值,要么得到一个错误,可能会出现一条建议,请真正给出答案。
你确实不能用 来做到这一点scanf("%d")。如果用户只是按回车键,则不会发生任何事情。因为scanf()还在等号。终端向前发送该行,但您的程序看不到它,因为scanf()它被吃掉了。您没有机会对用户的错误做出反应。
这也不是很有用。
因此,我建议一次使用fgets()或读取一整行输入。getline()这与终端给出的内容完全匹配,并且在用户输入一行后始终为您的程序提供控制权。您对输入行的处理取决于您,如果您想要一个数字,您可以使用atoi()、strtol()、 甚至sscanf(buf, "%d", &a)解析该数字。sscanf()没有与 相同的不匹配scanf(),因为它读取的缓冲区大小有限,当它结束时,它就结束了——该函数不能等待更多。
(fscanf()如果文件格式支持如何像任何空格一样跳过换行符,那么在常规文件上也可以。对于面向行的数据,我仍然使用fgets()and sscanf()。)
因此,不要使用上面的内容,而是使用这样的内容:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
Run Code Online (Sandbox Code Playgroud)
或者,实际上,检查too的返回值sscanf(),这样您就可以检测空行和其他无效数据:
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
Run Code Online (Sandbox Code Playgroud)
当然,如果您希望程序坚持执行,您可以创建一个简单的函数来循环 和 ,fgets()直到sscanf()用户屈尊执行他们被告知的事情;或者立即退出并出现错误。取决于您认为如果用户不想玩球,您的程序应该做什么。
您可以做类似的事情,例如通过循环getchar()读取字符直到scanf("%d")返回后换行,从而清除缓冲区中留下的任何垃圾,但这对于用户只是在空行上按 Enter 键的情况没有任何作用。不管怎样,fgets()会读到换行符,所以你不必自己做。
另一种选择(我从这里得到的)是通过使用assignment-supression option读取和丢弃换行符。为此,我们只需放置一种格式来读取%和之间带有星号的字符c:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
Run Code Online (Sandbox Code Playgroud)
scanf 然后将读取下一个字符(即换行符)但不将其分配给任何指针。
然而,最后,我会支持常见问题解答的最后一个选项:
或者,根据您的要求,您也可以忘记 scanf()/getchar(),使用 fgets() 从用户那里获取一行文本并自行解析。
getchar()在调用 second 之前使用scanf()。
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
64718 次 |
| 最近记录: |