scanf()将新行字符保留在缓冲区中
我有以下计划:scanf()将新行字符保留在缓冲区中,c,scanf,C,Scanf,我有以下计划: 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",&
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;
}
正如我在C语言书中读到的,作者说,scanf()
在缓冲区中留下了一个新行字符,因此,程序不会停在第4行让用户输入数据,而是将新行字符存储在c2中,并移到第5行
是这样吗
但是,这是否只发生在char
数据类型中?因为我在第1、2、3行中没有看到int
数据类型的问题。是否正确?在尝试解析字符以外的转换之前,函数会自动跳过前导空格。字符格式(主要是%c
;也包括扫描集%[…]
-和%n
)是例外;它们不会跳过空白
使用带前导空格的“%c”
跳过可选空格。请勿在scanf()
格式字符串中使用尾随空格
请注意,这仍然不会消耗输入流中留下的任何尾随空格,甚至不会消耗到行尾,因此如果同时使用或在同一输入流上使用,请注意这一点。我们只是让scanf在转换之前跳过空白,就像它在%d
和其他非字符转换中一样
请注意,非空白的“指令”(要使用)不是转换,例如
scanf中的文本(“order=%d”,&order)代码>也不会跳过空白。文本顺序
必须与要读取的下一个字符匹配
因此,如果要跳过前一行的换行,但仍需要固定字符串上的文字匹配,则可能需要“order=%d”
。使用scanf(“%c”和&c2)代码>。这将解决您的问题。在调用第二个scanf()之前使用getchar()
scanf("%c", &c1);
getchar(); // <== remove newline
scanf("%c", &c2);
scanf(“%c”和&c1);
getchar();// 另一个选项(我从中得到)是使用赋值抑制选项读取并丢弃换行符。为此,我们只需设置一种格式来读取一个星号介于%
和c
之间的字符:
scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3
scanf
随后将读取下一个字符(即换行符),但不会将其分配给任何指针
然而,最后,我要说的是:
或者,根据您的需求,您也可以忘记scanf()/getchar(),使用fgets()从用户那里获取一行文本并自己解析
为了回应我的帖子:我建议扔掉scanf()
,不要使用它,而是使用fgets()
和sscanf()
(*)
原因是,至少在类似Unix的系统中,默认情况下,CLI程序运行的终端会在程序看到用户输入之前对其进行一些处理。它缓冲输入,直到输入换行符,并允许一些基本的行编辑,如使退格工作
所以,你不可能一次只得到一个字符,或者几个字符,只是一整行。但这不是例如scanf(“%d”)
所处理的,相反,它只处理数字,然后停在那里,剩下的缓冲在C库中,供将来的stdio
函数使用。如果你的程序有,例如
printf("Enter a number: ");
scanf("%d", &a);
printf("Enter a word: ");
scanf("%s", word);
然后输入行123 abcd
,它会同时完成两个scanf()
s,但只有在给出换行符之后。第一个scanf();第二个scanf()
不会等待您输入另一行(因为输入缓冲区已经包含足够的内容来填充%s
转换)
这不是用户通常期望的
相反,他们希望按enter键完成输入,如果按enter键,您会得到一个默认值或一个错误,可能会有一个建议,请您真正给出答案
使用scanf(“%d”)
无法真正做到这一点。如果用户只是点击回车键,什么也不会发生。因为scanf()
仍在等待号码。终端向前发送该行,但您的程序没有看到它,因为scanf()
会吃掉它。你没有机会对用户的错误做出反应
这也不是很有用
因此,我建议使用fgets()
或getline()
一次读取一整行输入。这与终端提供的完全匹配,并且总是在用户输入一行后提供程序控制。如何处理输入行取决于您自己,如果您想要一个数字,可以使用:atoi()
,strtol()
,或者实际上是sscanf(buf),%d,&a)
sscanf()
与scanf()
没有相同的不匹配,因为它读取的缓冲区大小有限,当它结束时,它就结束了——函数不能再等待了
(fscanf()
如果文件格式支持像任何空格一样在换行符上浏览,那么在常规文件上也可以。对于面向文件的数据,我仍然会使用fgets()
和sscanf()
)
因此,与上面的内容不同,使用以下内容:
printf("Enter a number: ");
fgets(buf, bufsize, stdin);
sscanf(buf, "%d", &a);
或者,实际上,还要检查sscanf()
的返回值,以便我们可以检测空行或其他无效数据:
#包括
内部主(空)
{
常量int bufsize=100;
字符buf[bufsize];
INTA;
int ret;
字符字[bufsize];
printf(“输入一个数字:”);
fgets(buf、bufsize、stdin);
ret=sscanf(buf、%d、&a);
如果(ret!=1){
fprintf(stderr,“好的,您不必\n”);
返回1;
}
printf(“输入一个单词:”);
fgets(buf、bufsize、stdin);
ret=sscanf(buf,“%s”,字);
如果(ret!=1){
fprintf(stderr,“你让我难过。\n”);
返回1;
}
printf(“您输入了%d和%s\n”,一个字);
}