我正在使用 gcc(Ubuntu 4.8.2-19ubuntu1)4.8.2
我正在编写一个非常简单的脚本来将字符串作为输入并使用一些自定义消息进行打印。第一个用户输入T(没有时间取字符串),然后通过 fgets 输入。我使用this& this作为参考。
我得到一个非常奇怪的输出,即fgets正在添加一些额外的新行甚至循环不能正常工作T = 2它只询问输入一次。
任何人都可以解释我的片段有什么问题。提前谢谢!
#include<stdio.h>
#include<string.h>
int main()
{
int T;
scanf("%d",&T);
while(T--){
char str[100]={""};
int i;
printf("Hello\n");
fgets(str,80,stdin);
i = strlen(str)-1;
if(str[i]=='\n')
str[i]='\0';
printf("World\n");
printf("%s\n",str);
}
return 0;
}
请参阅T = 2的图像参考,即使T = 2,它只接受一次字符串,打印语句的顺序也不符合预期。
答案 0 :(得分:5)
这是因为您的scanf()
电话
scanf("%d",&T);
不会使用伴随您输入的换行符\n
。
当您输入T
时,您的输入为 2 输入。
scanf()
使用2
,看到\n
并停止消费,将\n
留在输入缓冲区中。
当fgets()
被调用时,它会看到缓冲区中的\n
并将其视为输入。
要解决这个问题,你有几个选择(按我主观偏好的降序排列):
使用fgets()
获取第一个输入,然后使用strtol()
解析它以获取T
。
在fgets()
之后添加额外的scanf()
。
添加getchar()
以消耗一个额外字符。如果您确定输入后只有一个\n
,则此方法有效。因此,例如,如果您键入 2 Space Enter ,它将不起作用。或者,您可以在while(getchar() != '\n');
之后使用scanf()
将所有内容消耗到新行,但如果空行是后续fgets()
次调用的有效输入,则可能会出现问题。< / p>
如果您的实施支持,您可以使用fpurge(stdin)
或__fpurge(stdin)
。
而且,非常重要的是,不使用fflush(stdin)
除非您的实施明确定义其行为。否则它是未定义的行为。您可以参考this question了解更多详情。另请注意,如果您的输入可以通过管道传输到程序中,fpurge()
和fflush()
方法可能无法正常工作。
答案 1 :(得分:1)
这一行
scanf("%d",&T);
读取输入,直到找到第一个非数字,即newline
。然后fgets()
读取第一个输入的换行符。
我建议使用fgets()
来读取数字。
fgets(str,80,stdin);
sscanf(str, "%d", &T);
答案 2 :(得分:1)
第一次调用scanf时,允许用户输入循环次数的整数。他们这样做,并使用回车来表示输入的结束。此时,scanf读取整数,但在流中留下行尾(\ n)。。
所以当你调用fgets时,fgets从流中获取直到它到达第一个换行符 - 在你的代码中,在第一个循环中,这是它遇到的第一个字符。
如果您在致电fgets之前丢弃换行符,则应获得所需的结果。您可以这样做,例如将前三行更改为:
int counter = 0;
while (true)
{
if (counter%2==0)
{
Thread.Sleep(5000);
counter++;
//set ON
}
else
{
Thread.Sleep(5000);
counter++;
//set off
}
if (counter==1000)
{
counter -= 1000;
}
}
尽管可能在风格上有更好的方法。
答案 3 :(得分:0)
在为第一个scanf键入2之后按“enter”时,输入流中有换行符。最初由fgets()消耗,因此它不打印任何内容(您用\0
替换换行符。)
在下一行中,您的输入会在World
后被读取并回显,因为您正在将其打印出来。