【问题标题】:C - fgets hangs when array not filledC - 数组未填充时 fgets 挂起
【发布时间】:2015-01-13 11:08:26
【问题描述】:

我正在从stdinfgets() 获取输入,并且似乎在缓冲区溢出方面遇到了一些麻烦。我添加了一个 while 循环,该循环旨在吃掉所有字符,但是我的代码运行了多次,并且应该只运行一次。

void play_game(void) {
    int ch; /* Waste */
    /* Max input from fgets */
    char c[8];

    enum cell_contents board[BOARD_HEIGHT][BOARD_WIDTH];

    init_board(board);

    while(!is_game_over(board)) {
        display_board(board);

        printf("Please enter a move [enter Q or ctrl-D to quit]: ");

        if(fgets(c, sizeof(c), stdin)) {
            printf("Entered: %s\n", c);
            struct move calculated_move = calculate_move(c);

            if(is_valid_move(calculated_move, board))
                player_move(calculated_move, board);
            else
                printf("That is an invalid move!\n");
        }

        /* eat excess data */
        if (strlen(c) == sizeof(c)-1)
            while((ch = fgetc(stdin)) != '\n' && ch != EOF);

        /* eat overfilled data */
        //read_rest_of_line();

    }

    printf("Game over!\n");
    game_over(board);
}

这是我的结果:

Please enter a move [enter Q or ctrl-D to quit]: E4, C4 gfgfd oigjdfogkf dohdfkho dk
Entered: E4, C4 
            +---+---+---+        
1           | o | o | o |        
            +---+---+---+        
2           | o | o | o |        
    +---+---+---+---+---+---+---+
3   | o | o | o | o | o | o | o |
    +---+---+---+---+---+---+---+
4   | o | . | o | . | . | o | o |
    +---+---+---+---+---+---+---+
5   | o | o | o | o | o | o | o |
    +---+---+---+---+---++---+---+
6           | o | o | o |        
            +---+---+---+        
7           | o | o | o |        
            +---+---+---+        
      A   B   C   D   E   F   G   
Please enter a move [enter Q or ctrl-D to quit]: Entered: gfgfd o
That is an invalid move!
            +---+---+---+        
1           | o | o | o |        
            +---+---+---+        
2           | o | o | o |        
    +---+---+---+---+---+---+---+
3   | o | o | o | o | o | o | o |
    +---+---+---+---+---+---+---+
4   | o | . | o | . | . | o | o |
    +---+---+---+---+---+---+---+
5   | o | o | o | o | o | o | o |
    +---+---+---+---+---++---+---+
6           | o | o | o |        
            +---+---+---+        
7           | o | o | o |        
            +---+---+---+        
      A   B   C   D   E   F   G   
Please enter a move [enter Q or ctrl-D to quit]: Entered: igjdfog
That is an invalid move!
            +---+---+---+        
1           | o | o | o |        
            +---+---+---+        
2           | o | o | o |        
    +---+---+---+---+---+---+---+
3   | o | o | o | o | o | o | o |
    +---+---+---+---+---+---+---+
4   | o | . | o | . | . | o | o |
    +---+---+---+---+---+---+---+
5   | o | o | o | o | o | o | o |
    +---+---+---+---+---++---+---+
6           | o | o | o |        
            +---+---+---+        
7           | o | o | o |        
            +---+---+---+        
      A   B   C   D   E   F   G   
Please enter a move [enter Q or ctrl-D to quit]: 

【问题讨论】:

  • fgets 不会写入超出缓冲区的末尾,只要您给它一个正确的大小。但是,如果它适合缓冲区,它可以添加换行符。
  • 至于您的问题,请尝试在调试器中逐行执行代码,同时注意变量及其内容。它可能会帮助您找出问题所在。
  • 另外,小心那个循环吃掉剩余的字符。如果用户输入了 6 个字符和一个换行符怎么办?那么strlen(c) == sizeof(c) - 1 也将成立,您将从 next 行开始读取字符(或者更确切地说,游戏似乎在fgetc 等待输入时锁定)。更好的检查是缓冲区中的最后一个字符是否为换行符。
  • 如果从stdin 中删除消耗剩余字符的循环会发生什么?
  • 我将如何处理这个约阿希姆?

标签: c fgets


【解决方案1】:

通过检查数组中的最后一个字符是否为新行来解决问题。

/* eat excess data */
if (strlen(c) == sizeof(c)-1 || c[sizeof(c)-1] != '\n')
    read_rest_of_line();

void read_rest_of_line(void){
    int ch;
    /* remove all characters from the buffer */
    while (ch = getc(stdin), ch != '\n' && ch != EOF);

    /* clear the error status of the input pointer */
    clearerr(stdin);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 2019-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多