2015-01-13 1 views
0

stdin에서 입력을 가져오고 fgets()으로 표시되며 버퍼 오버 플로우에 약간의 문제가있는 것 같습니다. 모든 코드를 먹는 while 루프를 추가했지만 코드가 여러 번 실행되고 한 번만 실행해야합니다.배열이 채워지지 않을 때 C - fgets가 응답하지 않습니다.

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]: 
+1

['fgets'] (http://en.cppreference.com/w/c/io/fgets)는 올바른 크기를 지정하면 버퍼의 끝 부분을 초과하여 쓰지 않습니다. 그러나 버퍼에 맞으면 개행 문자를 추가 할 수 있습니다. –

+0

당신의 문제에 관해서는 변수와 그 내용을 주시하면서 디버거에서 한 줄씩 코드를 단계별로 실행하십시오. 문제가 무엇인지 알아내는 데 도움이 될 수 있습니다. –

+1

또한 나머지 문자를 먹는 루프에주의하십시오. 사용자가 6 자 및 개행을 입력하면 어떻게 될까요? 'strlen (c) == sizeof (c) - 1' 또한 참일 것이고, * next * 라인에서 문자를 읽기 시작할 것입니다 (또는 오히려'fgetc'가 기다리는 동안 게임이 잠길 것 같습니다. 입력). 더 나은 검사는 버퍼의 마지막 문자가 줄 바꿈인지 아닌지입니다. –

답변

2

배열의 마지막 문자를 확인하여 문제가 해결되었습니다.

/* 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); 
} 
관련 문제