这里简单的代码我没有得到预期的输出。
#include<stdio.h>
int main()
{
char buf[1024];
while(1)
{
fgets(buf,strlen(buf),stdin);
printf("%s",buf);
printf("hello");
}
}
在上面的代码中,我想要从键盘输入的字符串,然后打印出来,然后你好。 据我所知fgets()是一个阻塞函数,直到我从键盘输入一个字符串并按下ENTER键,它将阻止程序直到那个时间。因此,当我运行它时,我希望如下
$ ./a.out
I input some text here <ENTER>
I input some text here
hello
但实际上我得到的输出是终端上印有“hello”的无限循环。为什么我的fgets()没有阻止该程序?有什么想法吗?
答案 0 :(得分:6)
问题是strlen(buf)
返回0因为buf [0]恰好是0(不保证)。您应该使用sizeof(buf)
代替:
fgets(buf,sizeof(buf),stdin);
答案 1 :(得分:2)
将fgets()
来电更改为:
fgets(buf,sizeof(buf),stdin)
// ^^^^^^
在未初始化的strlen()
上调用buf
将返回谁知道什么。 strlen()
有可能返回0
,fgets()
将立即返回。
答案 2 :(得分:2)
那是因为缓冲区的strlen
可能为零。你应该使用sizeof
代替,它给你数组的大小(1024)而不是它包含的字符串的长度(这里不确定)。
在您的特定情况下,{em> 可能是一个零大小的字符串(*buf == '\0'
),因为fgets
调用根本没有阻塞。实际上,自标准规定以来它也可以有一个长度:
fgets函数最多读取一个小于n指定的字符数 从流指向的流进入s指向的数组。没有额外的 在换行符(保留)或文件结束后读取字符。一个 在读入数组的最后一个字符后立即写入空字符。
实际上,作为尚未初始化的局部变量,buf
可能包含任何,因此您不明智地依赖它(如果它不包含根本就是null终结符,你可能会发现自己正在转移核心,因为strlen
运行结束了。)
如果您想要一个经过验证的真实输入函数,请参阅here。它具有缓冲区溢出保护,提示,最后删除换行符,并在行长太长的情况下清除行余数。我将复制下面的代码,使这个答案更加独立。
#include <stdio.h>
#include <string.h>
#define OK 0
#define NO_INPUT 1
#define TOO_LONG 2
static int getLine (char *prmpt, char *buff, size_t sz) {
int ch, extra;
// Get line with buffer overrun protection.
if (prmpt != NULL) {
printf ("%s", prmpt);
fflush (stdout);
}
if (fgets (buff, sz, stdin) == NULL)
return NO_INPUT;
// If it was too long, there'll be no newline. In that case, we flush
// to end of line so that excess doesn't affect the next call.
if (buff[strlen(buff)-1] != '\n') {
extra = 0;
while (((ch = getchar()) != '\n') && (ch != EOF))
extra = 1;
return (extra == 1) ? TOO_LONG : OK;
}
// Otherwise remove newline and give string back to caller.
buff[strlen(buff)-1] = '\0';
return OK;
}
答案 3 :(得分:0)
您应该使用sizeof(buf)而不是strlen(buf),如下所示:
fgets(buf,sizeof(buf),stdin);
或直接:
fgets(buf,1024,stdin);