在fgets之后获得键盘输入

时间:2011-03-10 22:13:54

标签: c stdin fgets scanf

对于我的生活,我不能与c弦和输入/输出相提并论。

对于我的程序,我只需输入一个字符串,它将在以下代码中处理:(已定义tmpstring和ch)

对于我的输入,我写在终端:echo“test”| ./program

    int main(int argc, char *argv[]) {
    char tmpstring[2048];
    int ch;
    int r;
    int c;

    fgets(tmpstring, sizeof tmpstring, stdin);
    while((ch = fgetc(stdin))!= EOF && ch != '\n');
    tmpstring[strlen(tmpstring)-1]='\0';

    strncpy(opponent, tmpstring+1, strlen(tmpstring+1));

    move();

move();

    char buffer[2048]={0};
    int r, c;
    r=0; c=0;
    printf("Your move (row column):");
    if((fgets(buffer, sizeof buffer, stdin)==NULL) || ((sscanf(buffer,"%d %d", &r, &c))!=2)){
            printf("Invalid input. Please insert two numbers separated by whitespace.\n");
            exit(1);
    }
    //continues

执行此操作直接进入无效输入而不需要更多输入。我已经阅读了关于你不应该如何清除stdin(并且这是不可能的),但我真的不知道该怎么做。我显然试图用while循环的第二部分“转储”stdin。我改变了&&在第一个条件之后||在while循环中。没变。总的来说,在使用过fgets后我怎么能要求更多的输入?

*编辑:更多代码并将原始while循环分开

1 个答案:

答案 0 :(得分:0)

这种问题已在别处讨论过 我将从这里复制我自己帖子的一部分:

Max string length using scanf -> ANSI C

  • 通过调用my_scanf()库,联合stdarg.hfgets()的组合,定义了具有可变参数数量的函数vsscanf()
  • 该函数旨在以正确的方式处理fgets()sscanf()的组合(实际上,我们必须使用vsscanf()才能正确处理参数列表)。
  • 输入被读取到字符的上限。如果输入超过此限制,则会被截断。 '\ n'处理正确。该函数返回与scanf()返回的值相同的值。因此,您可以使用my_scanf()代替。

这里有代码:

#include <stdio.h>
#include <stdarg.h>

int my_scanf(const char* fmt, const unsigned int maxbuff, ...) {
    va_list ptr;
    int ret;

    if (maxbuff <= 0)
       return EOF; /* Bad size for buffer[] */

    char buffer[maxbuff+1];
    buffer[maxbuff-1] = '\0';  /* Quick buffer cleaning... */

    if (fgets(buffer, maxbuff+1, stdin) == NULL)
       return EOF; /* Error detected */
    else {
        if ((buffer[maxbuff-1] != '\n') && (buffer[maxbuff-1] != '\0'))
            /* Condition logically equivalent to:
                   fgets() has not reached an '\n'
            */
            while (getchar() != '\n')
               ; /* "Flushing" stdin... */

        va_start(ptr, maxbuff);
        ret = vsscanf(buffer, fmt, ptr);
        va_end(ptr);
        return ret;
    }    
}

#define MAXBUFF 20
int main(void) {
   int x; 
   float z;
   int scanf_ret = my_scanf("%d %g", MAXBUFF, &x, &z);
   printf("\nTest:\n x == %d\n z == %g\n scanfret == %d", x, z, scanf_ret);
   getchar();   
   return 0;   
}

函数my_scanf()具有原型

int my_scanf(const char* fmt, const int maxbuff, ...);
  • 它接受格式字符串fmt,其行为方式与任何其他scanf()相同 - 就像这样。
  • 第二个参数是将从标准输入(键盘)有效接受的字符的最大数量。
  • 返回值为 int ,如果EOF没有意义,或者发生了一些输入错误,则为maxbuff。如果返回非负值,则与标准函数sscanf()vsscanf()返回的值相同。

    1. 在函数内部,maxbuff增加1,因为fgets()为额外的'\ 0'字符腾出了一些空间。
    2. 立即丢弃maxbuff的非正值。
    3. fgets()会读取stdin(键盘)中的字符串,其中包含最多maxbuff个字符,包括'\ n'。
    4. 如果用户输入了一个非常长的字符串,那么它将被截断,并且需要某种“刷新”机制才能将所有字符丢弃到下一个'\ n'( ENTER )。如果没有,下一个键盘读取可能有旧字符,根本不需要。
      • “刷新”的条件是fgets()在阅读stdin后未达到'\ n'。
      • 如果且仅当buffer[maxbuff - 1]不等于'\ 0'或'\ n'时才会出现这种情况。 (检查!
    5. 最后,使用stdarg.h 和函数vsscanf()的合适(和标准)组合来处理变量参数列表。