【问题标题】:How to check if there are some some characters left in stdin after scanf?如何检查scanf后stdin中是否还有一些字符?
【发布时间】:2013-05-26 16:50:07
【问题描述】:
scanf("%9s", line);

我从标准输入中读取了一行(最多 9 个符号),然后我想检查我是否从用户输入中读取了所有字符。有什么优雅的方法吗?

【问题讨论】:

  • 你试过feof()吗?
  • 你的意思是 feof(stdin) 吗?我刚刚尝试过,无论我输入什么长度的字符串,它都会返回 0
  • 'feof(stdin)' 无论我输入什么长度的字符串都返回 0'——这告诉你下一个 I/O 操作还有一个换行符要读取......唯一一次赢了如果您遇到没有最终换行符的 EOF,则不会留下任何数据。
  • 实际上有一些标准输入的实现不起作用,并且无论流上的实际内容如何,​​都会导致始终为 0。

标签: c stdin scanf


【解决方案1】:

feof() 将允许您检查标准输入缓冲区是否为空。否则,如果您想进一步检查内容...使用类似的内容..

while ( fgets(buf,BUFSIZ,stdin) != NULL ) 
  {     printf("%s",buf); }

这里的 buf 将是保存 BUFSIZ 字节数据的数组/字符串

【讨论】:

  • feof() 一直返回 0。也许我正在以错误的方式读取字符串?你能举个例子说明如何在阅读完所有内容后让 feof() 不等于 1 吗?
  • 在控制台中你必须按下 (Linux) 来使 feof() 返回 1。也许……像 select(), poll(), ... 可以解决你的问题。
【解决方案2】:

建议将人工输入与解析分开。人们输入最意想不到的字符。并且不变,我发现单独正确处理这些问题更容易。

读入行(这个我放在自己的函数里)

char buf[1024];
char *retval;
retval = fgets(buf, sizeof(buf), stdin);
// if I/O trouble reading ...
if (!retval) {
  handle error
} 
// if End-of-line missing (as buffer was filled) ...
if (!strchr(buf, '\n')) {
  handle error
} 
// Toss '\n'
buf[strlen(buf) - 1] = '\0';

然后解析数据

sscanf(buf, "%9s", line); 
if (strlen(buf) > 9) {
  // You have extra data
  }

【讨论】:

  • 当您已经知道换行符在哪里时,您可以使用 if ((retval = strchr(buf, '\n')) == 0) { ...handle error... } *retval = '\0'; 避免对输入字符串进行第二次扫描。
  • @Jonathan Leffler 肯定是正确的。通常我会反过来做,找到字符串长度,看看它是否> 0,然后如果最后一个字符是\n,则将其删除。但这种方法看起来不太清楚。
  • 是的:您可以使用strlen()strchr(),但在这种情况下您不需要同时使用两者。但是一般的方法是正确的; fgets()加分析一般比较好。即使这样,feof() 也不会返回 true,直到 fgets() 返回 0。它不知道下一次读取什么时候会返回任何内容;它知道最后一次读取什么时候没有返回任何内容。
  • @Jonathan Leffler 我遇到了类似的 foef() 问题。输入和解析分离的另一种用途:如果给定的解析失败,可以很容易地尝试另一种解析。例如。读取评估为真的文本布尔值:它可能是“T”、“True”、“1”。它可能需要更复杂的解析 scanf() 函数族提供的内容。
【解决方案3】:

您可以先将数据读入更大的字符串,然后再获取其长度。 在某些时候,您只想摆脱输入缓冲区中留下的任何内容。 为此,您可以在某些系统上使用 fflush 并在所有其他系统上使用 fpurge。

这里有一些示例代码,您可以使用它们来填充一个大缓冲区并清除其余部分。如果其中有任何特殊字符,清理功能将删除最后的换行符或提前结束字符串。

void userInput( char * str, int size );
void get( char * str, int size );  
void clean( char * str, int size );  
void flush( void );

void userInput( char * str, int size )
{
    get( str, size );
    clean( str, size );   
    flush();
}

void get( char * str, int size )
{
    memset( str, 0, size );
    fgets ( str, size, stdin );
}

void clean( char * str, int size )
{
    char * c;   
    str [size -1] = 0;
    c = str;
    while( *c >= ' ' || *c < 0 ) ++c;
    *c = 0;
}

void flush( void )
{
    //the ifdef approach does not work in reality.
    //this is a pseudo case for your benefit.
    #ifdef fpurge 
        fpurge(stdin);
    #else
        fflush(stdin);
    #endif
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-15
    • 2011-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多