2013-07-15 3 views
0

저는 C 프로그래밍에 대한 책을 읽고 있는데 예제를 이해하지 못합니다. 또는 더 정확하게 나는 왜 그것이 작동해서는 안되기 때문에 그것이 효과가 있는지 이해하지 못한다.fgetc 프로그램 이해

코드는 간단하며 텍스트 파일의 내용을 읽고 출력 영역에 출력합니다. 내가 이해할 수있는 한, 나는 단지 한 번만 int를 읽으므로 while 루프 안에 있어야한다고 생각하겠다. 현재 출력 된 후 다음 int를 읽어야합니다. 글쎄,이 코드는 실제로 잘 작동하므로 누군가 내 잘못을 설명 할 수 있기를 바랍니다. 감사!

#include <stdio.h> 

int main(int argc, char *argv[]) { 
    FILE *stream; 
    char filename[67]; 
    int ch; 
    printf("Please enter the filename?\n"); 
    gets(filename); 
    if((stream = fopen(filename, "r")) == NULL) { 
     printf("Error opening the file\n"); 
     exit(1); 
    } 

    ch = fgetc(stream); 
    while (!feof(stream)) { 
     putchar(ch); 
     ch = fgetc(stream); 
    } 

    fclose(stream); 
} 
+0

이가 아닌 좋은 품질의 코드. 답에서 볼 수 있듯이 'feof'를 전혀 피할 수 있습니다. 여전히'feof'를 사용하면 두 개의'fgetc'을 사용할 필요가 없습니다 : 충분해야합니다'while (! feof (stream)) putchar (fgetc (stream));' –

+0

사실,이 코드는 1 바이트 스트림 !!! –

+0

모든 답변을 주셔서 감사합니다. 모든 답변을 받아 들일 수 있기를 바랍니다. – Linus

답변

2

난 당신 때문에 무엇이 일어 났는지를 결정하기 위해 feof()의 혼란 생각 :

문서 : 0에서 다른 값을 반환 스트림에 관련된 파일의 끝 표시가 세트인지 여부를 int feof (FILE * stream);

확인, 그렇다면.

인디케이터는 일반적으로 파일 끝나에서 읽으려고 시도한 스트림의 이전 작업에 의해 설정됩니다.

ch = fgetc(stream);  <---"Read current symbol from file" 
    while (!feof(stream)) { <---"Check EOF read/returned by last fgetc() call" 
     putchar(ch);  <---"Output lasts read symbol, that was not EOF" 
     ch = fgetc(stream); <---"Read next symbols from file" 
    } 
    <-- control reach here when EOF found 

훨씬 더 좋은 방법은 루프를 작성하는 것입니다 같은 : 또한

while((ch = fgetc(stream))!= EOF){ <--" Read while EOF not found" 
    putchar(ch); <-- "inside loop print a symbol that is not EOF" 
} 

, 참고 : int fgetc (FILE * stream);

현재 내부 파일 위치 표시가 가리키는 문자를 반환 지정된 스트림의 그러면 내부 파일 위치 인디케이터가 다음 문자로 넘어갑니다. 호출 될 때 스트림 파일의 마지막에있는 경우

는 함수 EOF 복귀하고 스트림 파일의 끝을 표시 설정 (무엇이 일어 났는지를 결정하기 위해 feof). 함수 EOF 복귀하고 스트림 (ferror 함수)에 대한 오류 표시기를 설정하는 판독 오류가 발생경우

. 여기

+0

이 코드는 1 바이트 파일을 출력하지 못합니다 !!! –

+1

@LS_dev 어떤 코드? 내가 더 나은 방법은? '이라는 코드는 정상적인 상황에서 파일의 크기에 관계없이 적어도 실패하지 않을 것이라고 확신합니다. –

+0

모든 것을 설명해 주셔서 대단히 감사합니다. 매우 유용합니다! – Linus

1

귀하가 보는 바와 같이 내부와 외부입니다. 바깥 쪽은 첫 번째 문자를 읽는 책임이 있습니다 (파일의 끝 부분 일 수 있습니다. 어쨌든 입력되지 않고 아무 것도 인쇄되지 않습니다). 그런 다음 루프에 들어가서 문자를 넣고 다음 문자를 읽습니다. 읽기 문자가 파일의 끝이 아니라면 루프가 계속됩니다.

1

fgetc()char(byte)을 읽고 해당 바이트를 반환합니다. 바이트 값 읽기는 읽기 포인터가 사용 가능한 위치에 따라 다릅니다.

일단 fgetc()가 성공적으로 1 바이트를 읽으면 읽기 파일 포인터가 다음 바이트로 이동합니다 .so 파일을 읽으면 next byte이 출력이되고 EOF를 반환하는 파일의 끝을 찾을 때까지 계속됩니다 . 이 같은 외측 fgetcwhile가 제거되면

1

:

while (!feof(stream)) { 
    putchar(ch); 
    ch = fgetc(stream); 
} 

ch 될 것라고 처음 putchar(ch)을 초기화되지 않은.

그런데 버퍼 오버플로가 발생할 수 있으므로 gets을 사용하지 마십시오. 대신 fgets 또는 gets_s을 사용하십시오. gets은 C11에서 제거되었습니다.

+0

@LS_dev 아니요,'gets '는 버퍼 오버 플로우를 일으킬 수 있다고 말하면 버퍼의 크기를 모르기 때문입니다. 'fgets'에는이 문제가 없습니다. http://c-faq.com/stdio/getsvsfgets.html –

+0

My bad!너의 권리,'fgets'은 완충기 측을 고려한다! –

1

fgetc이 (가) while (!feof(stream)) (으)로 전화를 걸고 있습니다.

1

사실이 부분 :

while (!feof(stream)) { 
     putchar(ch); 
     ch = fgetc(stream); 
    } 

꽤 안전하지 않은 당신은 그런 EOF (here 이유를) 확인하지 않도록해야합니다.

방법은 fgetc을 사용하여 파일을 읽어야 그렇게 같다 :

int ch; 
while ((ch = fgetc(stream)) != EOF) 
{ 
    printf("%c", ch) 
} 
+0

'printf ("% c", c)'대신에'putchar (ch);' –

+0

네가'putchar'을 사용하는 것은 분명히 괜찮습니다.'printf'와 같은. – Nobilis

1

귀하가 제공 한 코드는이 'CH =는 fgetc (스트림);' While 루프 전에 또한 'ch = fgetc (스트림);' 루프 본문 내에서 올바르게 진술하면 루프 내의 문이 한 번에 하나씩 스트림에서 ch를 검색한다는 것은 논리적입니다.

1

이것은 기능 코드가 아닙니다. 파일의 마지막 문자는 출력되지 않습니다. fgetc은 마지막 문자를 읽고 포인터는 파일의 끝에 있습니다. 따라서 while을 검사하면 !feof이 false를 반환하고 읽기 문자가 출력되지 않습니다. feof은 파일 끝나기 후에 읽을 수 없습니다. 빈 파일의 경우 fgetcfeof 전에 호출됩니다! 콘솔 처리에 약간의 혜택이없는 한 는이 더 나은 옵션이 존재합니다 무엇이 일어 났는지를 결정하기 위해 feof 사용 :

while (!feof(stream)) { 
    ch=fgetc(stream); 
    putchar(ch); 
} 

feof을 사용하지 않고 - 더 이상 문자가 없을 때 fgetc 반환 EOF이 때문에 :

while ((ch=fgetc(stream))!=EOF) putchar(ch); 
관련 문제