fgets()
的好处在于它会将行终止符换行符 ('\n'
) 放入输入缓冲区中。你所要做的就是寻找它。如果存在,你就得到了一整行的输入。如果不存在,那么还有更多内容需要读取。
因此,策略是:
fgets( s, size_of_s, stdin );
char * p = strpbrk( s, "\r\n" );
if (p)
{
*p = '\0';
return s; (the complete line of input)
}
如果
p
是
NULL
,则还有更多的工作要做。由于您希望简单地忽略过长的行,这与丢弃输入是相同的。使用简单的循环来进行处理:
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
流通常在后台由C库或操作系统(或两者)进行缓冲,但即使它们没有,这也不是太大的开销。(在玩“我是优化编译器”之前,请使用分析器。不要对C库做出不好的假设。)
一旦你把不想要的东西都扔掉了(到EOL),确保你的输入不是EOF并循环询问用户再试一次。
将所有内容放在一起
char * prompt( const char * message, char * s, size_t n )
{
while (!feof( stdin ))
{
printf( "%s", message );
fflush( stdout );
if (!fgets( s, n, stdin )) break;
char * p = strpbrk( s, "\r\n" );
if (p)
{
*p = '\0';
return s;
}
int c;
do c = getchar(); while ((c != EOF) && (c != '\n'));
}
return NULL;
}
现在你可以轻松地使用这个实用函数:
char user_name[20]; // artificially small
if (!prompt( "What is your name (maximum 19 characters)? ", user_name, sizeof(user_name) ))
{
complain_and_quit();
// ...because input is dead in a way you likely cannot fix.
// Feel free to check ferror(stdin) and feof(stdin) for more info.
}
这个小的prompt
函数只是一种您可以编写的辅助实用程序函数的示例。您可以做一些像为用户不遵守您的指令而添加额外提示的事情:
你叫什么名字?John Jacob Jingleheimer Schmidt
唉,我只能输入19个字符。请再试一次:
你叫什么名字?John Schmidt
你好 John Schmidt。
fgets()
由于长度而截断一行,那么该行的其余部分不会被丢弃,而是留在输入中。fgets()
保留换行符,因此如果没有换行符(并且缓冲区已满),则该行太长了。 - Weather Vane