在同一个程序中使用scanf和fgets?
我需要做以下事情:
int main(void) { char a,b,cstring; printf("please enter something"); scanf("%c %c",&a,&b); prinf("thanks, now some more"); fgets(cstring,35,stdin); }
问题是每当我从scanf输入第一个变量时,它会跳到程序的末尾。 我该如何做多个输入?
第一个问题是scanf()
读取两个字符,但之后不读取换行符。
这意味着你的fgets()
读取换行符并完成。
你很幸运你的程序没有崩溃。 你告诉fgets()
它得到一个包含35个字符的数组,但是不是传递数组,而是传递字符(不是字符的地址,甚至)。 这也告诉我们你不包括启用足够的警告编译或者没有足够重视编译器告诉你的内容。 #include
(你不能根据C标准可靠地使用scanf()
而没有范围内的scanf()
原型),并且你没有
您应该收到编译器警告。 例如,GCC 4.6.0说:
/usr/bin/gcc -g -I/Users/jleffler/inc -std=c99 -Wall -Wextra -Wmissing-prototypes \ -Wstrict-prototypes -Wold-style-definition xxx.c xxx.c: In function 'main': xxx.c:7: warning: implicit declaration of function 'prinf' xxx.c:8: warning: passing argument 1 of 'fgets' makes pointer from integer without a cast
并且,它还没有注意到printf()
的拼写错误,直到我尝试链接并且编译器通过说“不知道什么是prinf()
是我的鼻子!”。
如果你的编译器至少没有给出第二个警告,那么给自己一个更好的编译器。
评论:
如何阻止它在阅读换行后?
问题不在于阻止scanf()
读取换行符; 问题实际上是如何让它读取它,以便fgets()
在下一行输入中获得清晰的运行。 它实际上是非常棘手的 – 我很少使用scanf()
一个原因(但我经常使用sscanf()
)。 这可以完成简单输入的工作:
#include int main(void) { char a,b,cstring[35]; printf("please enter something"); scanf("%c %c%*c", &a, &b); printf("thanks, now some more"); fgets(cstring, 35, stdin); printf("OK: I got %c and %c and <<%s>>\n", a, b, cstring); return 0; }
%*c
读取一个额外的字符(换行符)而不将其分配到任何地方(这是因为*
)。 但是,如果第二个非空白后有多个字符,则无济于事。 我可能会写一个循环来读取换行符:
#include int main(void) { char a,b,cstring[35]; int c; printf("please enter something"); scanf("%c %c", &a, &b); while ((c = getchar()) != EOF && c != '\n') ; printf("thanks, now some more"); fgets(cstring, 35, stdin); printf("OK: I got %c and %c and <<%s>>\n", a, b, cstring); return 0; }
请注意, getchar()
返回一个int
而不是一个char
。 这可靠地丢弃第一行输入上的所有内容。 它还显示了如何回显您所读取的内容 – 调试的一个重要部分。
这是未定义的行为。 您的cstring
变量尽管名称是单个字符,但您尝试将最多35个字符读入其当前值所指向的字符。 换句话说, cstring
的当前字符将转换为指针,它将尝试在那里写入您的输入。 这将是一个介于0到255之间的内存位置(最有可能)。
这就是导致您的细分违规的原因。 从这样的事情开始:
#include int main(void) { char a,b,cstring[99]; printf("please enter something"); scanf("%c %c",&a,&b); printf("thanks, now some more"); fgets(cstring,35,stdin); return 0; }
或者,可能更好:
#include int main(void) { char a,b,cstring[99]; printf("please enter something"); fgets(cstring,35,stdin); sscanf(cstring,"%c %c",&a,&b); printf("thanks, now some more"); fgets(cstring,35,stdin); return 0; }
或者,如果您想要一个更强大的用户输入解决方案,请参阅此处 。 这是一个经过试验和测试的方法,具有非常好的错误检查function。
问题是当流程到达fgets()时,此API首先查看stdin的输入,并在那里找到一个迷路’\ n’。 至于表示此API在遇到EOF或’\ n’时返回的fgets(),因为fgets()从stdin得到’\ n’,所以它执行时无需等待用户输入内容,因为API返回条件满足。
解决问题的方法是使用getchar(); 在scanf之后并忽略scanf()留下的额外字符。 例如:
scanf("%lf",&e); getchar(); fgets(t,200,stdin);
要么
其他解决方案可以是使用带有fgets的sscanf。 例如:
#include int main() { int j;char t[200]; fgets(t,200,stdin); sscanf(t,"%d",&j); }
你可以在使用scanf后使用fflush(stdin)清除问题