2013-04-10 3 views
0

아래는 내 C 코드입니다. 첫 번째 입력은 아름답게 작동하지만 두 번째 입력은 무한 루프를 발생시킵니다. 버퍼를 플러시했습니다.이 문제를 해결할 방법이 없습니다. fgets두 번째 입력 char * 무한 루프를 만듭니다

#include <stdio.h> 
#include <string.h> 
#include <unistd.h> 
#include <sys/types.h> 

#define MAXARG 7 

int main() 
{ 
    char buf[256]; 
    char* arg[MAXARG]; 
    char* s; 
    char* save; 
    int argv; 

    static const char delim[] = " \t\n"; 
    int pid, status; 

    while(1){ 
     printf("MyShell: "); 
     fgets(buf, sizeof(buf), stdin); 
     fflush(stdin); 
     argv = 0; 

     s = strtok_r(buf, delim, &save); 

     while(s){ 
      arg[argv++] = s; 
      s= strtok_r(NULL, delim, &save); 
     } 

     arg[argv] = (char*) 0; 

     if(!strcmp(arg[0], "quit")) 
      break; 
     if((pid = fork()) == -1) 
      perror("fork failed..."); 
     else if(pid != 0){ 
      pid = wait(&status); 
     } 
     else{ 
      execvp(arg[0], arg); 
     } 
    } 
    return 0; 
} 
+0

기술적으로 입력 스트림에서'fflush'를 사용하는 것은 정의되지 않은 동작입니다. –

+0

문제에 관해서는 디버거에서 한 줄씩 코드를 시도해 볼 수 있습니다. 도움이 될 수도 있습니다. –

+0

위의 fgets를 사용하십시오 –

답변

0

사용 fflush .. u는 당신이 메시지를 입력하기 전에 stdin를 세척 할 필요가 ..

당신이

+0

C 표준의 2 단락 7.21.5.2에서는 'fflush (stdin);'이 정의되지 않은 동작임을 분명히합니다. * 스트림이 출력 스트림 또는 업데이트를 가리키는 경우 스트림에서 가장 최근의 연산이 입력되지 않은 경우 fflush 함수는 해당 스트림에 대해 작성되지 않은 데이터를 호스트 환경에 전달하여 파일에 기록합니다. 그렇지 않으면 동작은 입니다. * – Sebivor

+0

입력 스트림에서 'fflush'에서 예상하는 동작을 설명해 주시고, 별이 가지고있는 우연의 일치에 의존 할 필요가 없음을 보여 드리겠습니다. 원하는 행동을하기 위해 마술처럼 정렬됩니다. – Sebivor

+1

을 의미합니까? 내 xcode는 그런 헤더를 찾을 수 없다고 말했다. 어쨌든 fpurg() 일은 당신 말이 맞습니다. 감사. 나는 그것에 대해 생각하지 않았다. –

0

이 문제 .. stdio_ext 헤더에 linux__fpurge을 사용할 수 있습니다 fgets()으로 전화하면 fflush()으로 전화하여 작업을 수행하십시오 ... while 번으로 돌아가서 fgets()으로 다시 전화하십시오. 그러나은 테스트하지 않았습니다.fgets()에서 얻을 수있는 모든 것을 보장 할 수는 있습니다. 이제 while 루프가 끝없이 빠른 언급의 EOF

0

가치보다 다른 뭔가를 반환하는 fgets() 대기 순환된다

/* Read and discard the remainder of a line of input, because the remainder of 
* the line isn't of interest to us... 
*/ 
void discard_line(FILE *f) { 
    int c; 
    do { 
     c = fgetc(f); 
    } while (c >= 0 && c != '\n'); 
} 

fflush가되지 않습니다 : 사람들이 fflush(stdin); 을 쓸 때, 그들은 일반적으로 같은 의미 stdin과 같은 입력 스트림에서 작동하도록 정의되었습니다. fflush(stdin); 은 예상 한대로 수행 할 수도 있지만 우연의 일치입니다. 휴대성에 신경 쓰면 입력 전용 스트림에서 fflush을 사용하지 마십시오.

실제로 이전에 가지고 있지 않은 기능에 대한 매뉴얼 페이지를 읽으면서 특히 the section entitled "RETURN VALUE" of the "fgets" manual에주의를 기울여보십시오. 루프의 조건에 반환 값을 포함시킬 수도 있습니다.

/* Note how fflush is used on an output stream to ensure data is written 
* immediately to stdout. You'll only need to do this when your data doesn't 
* end in '\n', because data may not be written until a '\n' is written. 
*/ 
printf("MyShell: "); fflush(stdout); 
while (fgets(buf, sizeof buf, stdin) == buf) { 
    /* Find either the first '\n' or the first '\0', so we can work out whether 
    * or not to discard anything... 
    */ 
    size_t length = strcspn(buf, "\n"); 
    if (buf[length] != '\n') { 
     /* If the line doesn't end in '\n', then we've read only part of a line. 
     * Discard the rest? Okay... 
     */ 
     discard_line(stdin); 
    } 

    /* Remove the '\n', if there is one. Otherwise, replace '\0' with '\0' ;) */ 
    buf[length] = '\0'; 
    /* TODO: Insert non-fflush(stdin)-related code here */ 

    printf("MyShell: "); fflush(stdout); 
} 

PS 등이 있습니다. 나는 의견을 읽는 것이 좋습니다. 그들은 통찰력을 가질 수 있습니다.

+0

코딩 노하우를 배워 주셔서 감사합니다. 하지만 몇 가지 이유가 있습니다. 입력 논리를 귀하의 논리로 대체했지만 여전히 무한 루프에 빠져 있습니다. 내가 아직도 시도 할 수있는 어떤 생각을 남겨두고 있니? –

+0

테스트에 사용하는 명령은 무엇입니까? – Sebivor

+0

"ls", "ps", "cal 04 2013"을 테스트했습니다. 그러나 문제는 모든 두 번째 명령이 무한 루프가된다는 것입니다. 거기에 처음으로 몇 가지 명령을 입력하고 지우기, 그리고 다시 명령을 넣어 경우에만 문제가 발생하지 않는 하나의 예외가있다 –

관련 문제