2011-11-07 7 views
0

글쎄,이 코드는 방의 페인트 품질을 찾는 데 사용됩니다. 기본적으로Scanf는 루핑을 계속합니다

void get_room_size(char room_id, int * length, int * width) { 
    while (*length <= 0 && *width <= 0) { 
     printf("Enter length and width of room %c in feet: ", room_id); 
     if (scanf("%d,%d", length, width)) { 
      if (*length <= 0) { 
       printf("###Error! Length must be a positive value!\n"); 
      } 
      if (*width <= 0) { 
       printf("###Error! Width must be a positive value!\n"); 
      } 
      printf("\n"); 
     } else { 
      printf("bad data"); 
      *length = 0; 
      *width = 0; 
     } 
    } 
} 

, 내가

을 입력하면, 1

이 미쳐 루핑 유지할 것이다. 뭐가 문제 야?

+0

을 읽을 방법 scanf() 성명에서 &을 넣어 말아 a '이므로 결코 읽히지 않습니다. –

답변

5

"미친"이유는 다음과 같습니다. scanfa으로 숫자로 표시되지 않으므로으로 읽지 못할 경우 이 파일 포인터를 넘기지 않습니다.

이것은 일반적으로 scanf 작업을 사용하지 않아야하는 한 가지 이유이며, 실패로 인해 파일 포인터가 불명확 한 위치에 남아있을 수 있습니다 (예 : 12 개 중 3 개에서만 스캔하는 경우).

다른 이유는 scanf는 의미 "형식 검사"당신은 하드 사용자 입력에 비해 포맷되지 않은 더 아무것도 찾을 수 누르면 될 것입니다.

어쨌든, 실패로 돌아갑니다. 파일 포인터가 고급 상태가 아니기 때문에 다음에 다시 fscanf을 실행하면 다시 a (그리고 계속해서)을 읽으려고 시도합니다.

사용자 입력을 처리하기위한 괜찮은 기능을 원하는 경우

여기보다 더 봐 :

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

#define OK  0 
#define NO_INPUT 1 
#define TOO_LONG 2 
static int getLine (char *prmpt, char *buff, size_t sz) { 
    int ch, extra; 

    // Get line with buffer overrun protection. 
    if (prmpt != NULL) { 
     printf ("%s", prmpt); 
     fflush (stdout); 
    } 
    if (fgets (buff, sz, stdin) == NULL) 
     return NO_INPUT; 

    // If it was too long, there'll be no newline. In that case, we flush 
    // to end of line so that excess doesn't affect the next call. 
    if (buff[strlen(buff)-1] != '\n') { 
     extra = 0; 
     while (((ch = getchar()) != '\n') && (ch != EOF)) 
      extra = 1; 
     return (extra == 1) ? TOO_LONG : OK; 
    } 

    // Otherwise remove newline and give string back to caller. 
    buff[strlen(buff)-1] = '\0'; 
    return OK; 
} 

이 의지 입력 사용자로부터 라인을, (억제 할 "%s"gets 또는 scanf 달리) 오버 플로우 보호.

입력이 너무 길면 줄 끝까지 플러시되므로 나머지 줄이 다음 입력 작업에 영향을 미치지 않습니다.

그런 다음 파일 포인터에 아무런 문제가없는 마음으로 버퍼 내용을 sscanf에 저장할 수 있습니다.

다음 테스트 프로그램

이를 사용하는 방법을 보여줍니다 AS를

int main (void) { 
    int rc; 
    char buff[10]; 

    rc = getLine ("Enter string> ", buff, sizeof(buff)); 
    if (rc == NO_INPUT) { 
     // Extra NL since my system doesn't output that on EOF. 
     printf ("\nNo input\n"); 
     return 1; 
    } 

    if (rc == TOO_LONG) { 
     printf ("Input too long [%s]\n", buff); 
     return 1; 
    } 

    printf ("OK [%s]\n", buff); 

    return 0; 
} 

를 제외하고, 유효한 크기의 방에 대한 귀하의 논리를 다시 검사 할 수 있습니다. 현재 가지고있는 방에서 7 피트 -42 피트로 입력 할 수 있습니다 :-)

입력시 특정 값으로 설정된 출력 값에 의존하는 것이 일반적으로 좋지 않습니다. 입력시 길이와 폭이 (예를 들어) 3과 4 인 경우이 함수는 사용자에게 입력을 요구하지 않고 바로 종료됩니다.

&& 대신 ||을 사용하면 첫 번째 문제를 해결할 수 있습니다. 두 번째는 함수 시작시 변수를 0으로 초기화하여 루프가 입력되도록합니다.완성도를 들어


, 다음과 함께합니다 (include 진술과 getLine() 기능) 위의 원래 조각이 약간 get_room_size() 기능을 수정 한 것을 결합 할 경우 :

static void get_room_size(char room_id, int * length, int * width) { 
    char buff[100]; 
    *length = *width = 0; 
    while ((*length <= 0) || (*width <= 0)) { 
     printf("Enter length and width of room %c in feet: ", room_id); 
     int rc = getLine (NULL, buff, sizeof (buff)); 

     if (rc == NO_INPUT) { 
      printf ("\nEnd of file encountered.\n"); 
      return; 
     } 

     if (rc == TOO_LONG) { 
      printf ("\nInput too long, please retry.\n"); 
      continue; 
     } 

     if (sscanf(buff, "%d,%d", length, width) != 2) { 
      *length = *width = 0; 
      printf ("\nInput not in desired form (<number>,<number>), " 
       "please retry.\n"); 
      continue; 
     } 

     if ((*length <=0) || (*width <= 0)) { 
      *length = *width = 0; 
      printf ("\nBoth length and width must be greater than zero, " 
       "please retry.\n"); 
     } 
    } 
} 

과 매우 간단한 테스트 main()를, 당신 ' 그것을하는 방법을 보여주는 완벽한 프로그램을 보게 될 것입니다.

int main (void) { 
    int len, wid; 
    get_room_size ('x', &len, &wid); 
    printf ("Length is %d, width is %d.\n", len, wid); 
    return 0; 
} 
+0

문자열을 읽은 다음 int로 구문 분석을 시도합니다. –

0

귀하의 scanf는 두 정수로 표시됩니다. A는 문자이고, 당신이 원하는 것 같아요 scanf ("% c", * room_id); scanf ("% d", length);

+0

방 ID가 전달 된 이후로 (그리고 변경할 수 있고 다시 전달할 수있는 포인터로 _not_) 방 ID가 이미 알려졌고 'printf'에 사용 된 것으로 판단됩니다. – paxdiablo

0

이 시도 내가 reccommend

당신이 별도로 않습니다

... 
     if (scanf("%d,%d", length, width) == 2) { 
      if (*length <= 0) { 
       printf("###Error! Length must be a positive value!\n"); 
      } 
      if (*width <= 0) { 
       printf("###Error! Width must be a positive value!\n"); 
      } 
      printf("\n"); 
     } else { 
      printf("bad data"); 
      *length = -1; 
      *width = -1; 
     } 
+0

원래 코드보다 파일 포인터가 앞으로 나아지지 않기 때문에 여전히'a, 1'에서 반복됩니다. – paxdiablo

+0

요령은 scanf()에서 상태를 올바르게 확인하는 것이 었습니다! – paulsm4

-1

을 당신은 너무 당신 '이 읽을 수있는 코드가없는

if (scanf("%d,%d", &length, &width)) 
+0

이 실수를 scanf() 구문에서 시도해보십시오. –

+1

이것은 문제가 아닙니다 ... scanf는 이미 길이와 너비를 가리 킵니다. – TheAJ

관련 문제