2016-11-16 13 views
4

그래서 :입력 문자가 버퍼에 끼어 들지 않도록하려면 어떻게해야합니까? 그때 주어진 작업을 수행할지 여부를 결정하기 위해 사용자에서 옵션을 읽고 있어요 다음과 같은 코드에서 C

printf("Do you want to execute %s: ", exe); 

char input = getchar(); 

if (input == 'y') { 
    return execute(exe); 
} return 0; 

나는 데 문제가를 그 라인 char input = getchar() 문자 후 (내가 엔터 키나 개행을 가정하고있어)가 stdin에 걸리면 내 execute() 함수에서 fgets() (읽는 중 stdin)을 호출하면이 멈추어진 문자를 먹어 버리고 사용자에게 필요한 입력을 요구하지 않습니다.

는 지금은 ... execute()를 호출하기 전에 호출하면 나를 위해 어떤 길잃은 문자를 '먹고'하는

void iflush() { 
    int c; 

    while ((c = getchar()) != EOF && c != '\n') { 
     continue; 
    } 
} 

을 다음 함수를 정의 할 수 있습니다 ...이 문제를 해결합니다. 그러나 이것이 왜 처음에 발생하는지 궁금해졌습니다. charstdin에서 가져 오는 더 적절한 방법이이 길잃은 문자를 일으키지 않고 내 다른 방법을 엉망으로 만들 수 있습니까? 나는 C에게 매우 익숙하며, 좋은 습관을 배우고 싶어합니다.

단순한 경우에도 일부 프로그램의 오류를 방지하기 위해 도우미 메서드를 추가해야한다는 것이 이상하게 보입니다. 나도 같은 문제가 있지만 fgetc()을 사용해 보았습니다.

+0

당신은 시도해 봤어'FFLUSH (표준 입력)'는'getchar가()'호출 문 다음에? – VHS

+0

그래, 아무 것도하지 않았어 – transiti0nary

+5

@VHS 정말 나쁜 조언 인 줄 알아? 'fflush (stdin);'은 정의되지 않은 동작을 호출합니다. –

답변

3

왜 이런 일이 발생했는지 궁금합니다. 당신이 문자가 %c (또는 fgetc())이 입력 스트림의 공백의 바깥을 무시하지 않습니다 때 때문에

그것은이다. 일부 형식 지정자 (예 : %d)는 입력 스트림에 남아있는 공백을 무시합니다. 그래서, 그것은 문제가 아닙니다. 그러나 %c은이를 무시하지 않습니다. 따라서 일반적으로 "먹기"기능을 사용합니다. (예 등 공간, 줄 바꿈으로) 공백 문자를 스캔하는 경우

는 스캔 할 수 당신이 어떻게 scanf()를 사용하여, 생각 하는가? fgets()을 사용하는 것과 같이 이 더 좋은 가지가 분명히 있습니다.

저는 C가 매우 새로워서 좋은 습관을 배우고 싶어합니다.

내 제안은 scanf()을 완전히 피하는 것입니다. 대신 fgets()을 사용하여 행을 읽은 다음 sscanf()을 사용하여 해당 행을 구문 분석 할 수 있습니다. 읽어 보시기 바랍니다 : Why does everyone say not to use scanf? What should I use instead?

한 가지 fgets()에 대해 알고 있어야하는 것입니다 당신이 입력 버퍼에 충분한 공간이있는 경우, 다음뿐만 아니라 개행 문자, 대부분의 사용자 입력에 방지 할 것 를 읽을 수 있습니다. 따라서 마지막 문자가 개행인지 확인한 다음 제거해야합니다.

당신은 같은 strcspn() 기능을 사용하여 얻을 수 있습니다 당신은 단지 하나 개의 문자를 읽고에 주로 관심이 있다면

char line[256]; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
line[strcspn(line, "\n")] = 0; /* remove the newline char if present */ 

, 다음 배열은 3 개 문자는 충분할 것이다. 아직 다치게하지 않는 큰 버퍼를 사용하여 :

char line[256]; 
char ch; 
if (fgets(line, sizeof line, stdin) == NULL) { 
    /* handle failure */ 
} 
if (sscanf(line, "%c", &ch) != 1) { 
    /* handle failure */   
} 
/* Now you can use 'ch' to check if it's 'y' */ 
+0

"한 문자 만 읽으면 배열 2 문자로 충분할 것"을 제외하고는 매우 좋습니다. 보통'char'를 읽으 려 할 때 사람들은'\ n'을 계산하지 않습니다. 아마도 : 문자, 줄 바꿈 및 null 문자에 대해 최소한 3 개가 필요할 것입니다. 최대가되어야한다고 생각하는 버퍼 크기를 두 번 추천하십시오. 256은 사용자 입력에 적합합니다. – chux

+0

'fgets()'는 버퍼에 공간이 없다면'\ n' 만 저장합니다. 따라서 2는 충분합니다 : 1 char 및 0 바이트. 그래서 하나의 char을 읽을 때 (개행이라 할지라도) 2 바이트의 버퍼 크기로 충분합니다. – usr

+0

사실, 다음 입력 작업을 위해''\ n ''이'stdin'에 남아 있습니다.''y \ n "'아래의 사용자가"one "문자 하나만 읽으면 OP가 피하고자하는 것처럼 보입니다. 코드가' '\ n' '을 포함하여 한 번에 한 문자 씩 읽을 필요가 있다면'fgetc()'만 사용하면된다. 이것은'fgets()'에 문제가있는 null 문자를 읽는 것을 처리한다. – chux