2017-01-26 3 views
1

사용자 입력을 사용하여 2 차원 배열을 채우고 있습니다. 그때 중첩 루프를 사용하여 한 줄에 사용자 입력 번호과 같이 배열을 채우기 위해 :C에서 stdin 파이프가 비어 있는지 확인

//User inputs: "1 2 3 4 5" 

for(i = 0; i < r; i++){ 
    for(j = 0; j < c; j++){ 
      scanf("%d", &arr[i][j]); 
    } 
} 

그러나 문제는 사용자가 5의 int를 입력하면 6 여지가있을 때, 그것은 또 다른 기다립니다 입력. 불충분 한 숫자가 있는지 어떻게 알 수 있습니까?

나는 이것을 사용하여 시도했지만 작동하지 않았다 당신이 실제로 소비하기 전에 스트림 및 테스트 문자로 미리 들여다 사용할 수 있습니다

for(i = 0; i < r; i++){ 
    for(j = 0; j < c; j++){ 
     if (!feof(stdin)){ 
      scanf("%d", &arr[i][j]); 
     } 
     else{ 
      printf("insufficient datapoints\n"); 
     } 
    } 
} 
+0

경우'는 scanf()가'반환하지 않는'파이프 가까이하지 EOF'. – Stargateur

+0

@ccpgh 어떻게해야합니까? –

+0

'fgets'와'strtok'을 사용 하시겠습니까? – BLUEPIXY

답변

1

한 가지 방법은 아래의 거친 예제 코드를 추가했습니다. 그런 다음 strtok()을 사용하여 입력 행을 토큰으로 분리하고 strtol()을 사용하여 토큰을 숫자로 파싱 할 수 있습니다. scanf()과 비교할 때 fgets을 사용하면 구조화되지 않은 사용자 입력을 훨씬 쉽게 처리 할 수 ​​있습니다.

아래 코드는이 작업을 수행합니다. 입력 행에 너무 많은 요소가 있거나 요소가 너무 적거나 요소 중 하나가 유효한 번호가 아니면 메시지가 인쇄되고 행을 다시 입력해야합니다.

사용자가 각 행을 입력하면 strtok()을 사용하여 행을 토큰으로 분리합니다. 토큰 분리 문자 목록은 delims[]에 저장됩니다. 토큰은 공백이나 탭으로 구분할 수 있습니다. 구분 기호 자체는 토큰의 일부가 아니므로 \r\n을 포함하면 이러한 문자가 줄의 마지막 토큰에 포함되지 않습니다.

토큰이 발견되면 가능한 경우 strtol()을 사용하여이를 정수로 변환합니다. strtol() 호출 후 tail 포인터는 숫자의 일부가 아닌 토큰의 첫 번째 문자를 가리 킵니다. tail이 종결자인 NUL을 가리키는 경우 전체 문자열이 숫자로 분석됩니다. 그렇지 않으면 입력이 좋지 않은 것으로 간주되어 행을 다시 입력해야합니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

#define BUF_SIZE 1000 

int main(void) 
{ 
    size_t r = 3; 
    size_t c = 5; 
    size_t i, j; 
    char buffer[BUF_SIZE]; 
    char *token; 
    char *tail; 
    const char delims[] = " \t\r\n"; 
    int arr[r][c]; 
    int temp_val; 

    printf("Enter rows of %zu data elements:\n", c); 

    for(i = 0; i < r; i++){ 
     j = 0; 

     if (fgets(buffer, BUF_SIZE, stdin) == NULL) { 
      perror("Error in fgets()"); 
      exit(EXIT_FAILURE); 
     } 

     token = strtok(buffer, delims); 
     while (token != NULL) { 
      temp_val = strtol(token, &tail, 10); 
      if (*tail == '\0') { 
       arr[i][j] = temp_val; 
       ++j; 
      } else {    // token not a valid number 
       j = 0; 
       break; 
      } 

      if (j > c) {   // too many input values 
       break; 
      } 

      token = strtok(NULL, delims); 
     } 

     if (j != c) { 
      printf("insufficient datapoints\n"); 
      --i;     // enter row again 
     } 
    } 

    for (i = 0; i < r; i++) { 
     for (j = 0; j < c; j++) { 
      printf("%5d", arr[i][j]); 
     } 
     putchar('\n'); 
    } 

    return 0; 
} 

샘플 상호 작용 :

Enter rows of 5 data elements: 
1 2 3 4 
insufficient datapoints 
1 2 3 4 5 6 
insufficient datapoints 
1 x 2 3 4 
insufficient datapoints 
1 2 3 4 x 
insufficient datapoints 
1 2 3 4 5 x 
insufficient datapoints 
1 2x 3 4 5 
insufficient datapoints 
1 2 3 4 5 
2 3 4 5 6 
3 4 5 6 7 
    1 2 3 4 5 
    2 3 4 5 6 
    3 4 5 6 7 
1

. (C에서의 정렬).

공백을 무시할 때 사용할 수 있습니다 (이 작업을 수행해야합니다).

이 엿보기 값을 사용하여 불충분 한 문자가 입력되었는지 나타낼 수도 있습니다.

실제 판독 (scanf) 전에 peek을 수행해야합니다.

는 한 번에 입력 줄을 읽어 fgets() 대신 scanf()의를 사용하여 포함 할 목표를 달성하기 위해

#include <stdio.h> 
#include <ctype.h> 

int r=3; 
int c=2; 

int arr[100][100]; // FIX magic 

int main(int argc, char** argv[]) { 

    for(int i=0; i<r; i++) { 
    for(int j=0; j<c; j++) { 

     if (feof(stdin)) { 
     // error check and error/normal exit etc. 
     printf("eof\n"); 
     } 

     char c=getchar(); 

     if (c=='\n') { 
     // error check and error/normal exit here 
     printf("newline\n"); 

     } else if (isspace(c)) { 
     // advance and remove them - watch for end of stream when winding 
     printf("advance and discard whiitespace\n"); 

     } else { // add check for isdigit 
     // push back 
     ungetc(c, stdin); 
     printf("ungetc\n"); 
     } 

     scanf("%d", &arr[i][j]); 
     printf("got %d\n", arr[i][j]); 
    }  
    } 

    return 0; 
}