EOF 란 무엇이며 어떻게 트리거합니까? [닫은]


12

이것은 내 C 소스 코드입니다.

Ubuntu에서 빌드하면 문자가 시작되지만 입력 ENTER또는 캐리지 리턴으로 끝나지 않으므로 프로그램을 종료하는 방법을 모르겠습니다 .

EOF는 무엇을 의미합니까? 어떻게 트리거 할 수 있습니까?

이 출처는 Dennis Ritchie의 저서에도 있습니다.

#include <stdio.h>
    /* count digits, white space, others */
main ()
{
  int c, i, nwhite, nother;
  int ndigit[10];
  nwhite = nother = 0;
  for (i = 0; i < 10; ++i)
    ndigit[i] = 0;
  while ((c = getchar ()) != EOF)
    if (c >= '0' && c <= '9')
      ++ndigit[c - '0'];
    else if (c == ' ' || c == '\n' || c == '\t')
      ++nwhite;
    else
      ++nother;
  printf ("digits =");
  for (i = 0; i < 10; ++i)
    printf (" %d", ndigit[i]);
  printf (", white space = %d, other = %d\n", nwhite, nother);
}

4
C 언어 -1에서 EOF와 같습니다. /usr/include/stdio.h매크로 상수로 정의됩니다
Edward Torvalds


@edwardtorvalds 입력 -1으로 입력이 작동하지 않습니다 :)
Sergiy Kolodyazhnyy

같은 Dennis Ritchie 책이 이것을 설명한다고 생각합니다.
andy256

또한 관련 : unix.stackexchange.com/questions/110240/... (이 질문에 게시 된 답변 중 어느 것도 완전히 정확하지 않습니다.)
fkraiem는

답변:


23

Tl; dr

마지막 입력 플러시 직후에 CTRL+ D키 를 사용하여 터미널에서 실행되는 프로그램에서 일반적으로 EOF를 트리거 할 수 있습니다 .


EOF는 무엇을 의미합니까? 어떻게 트리거 할 수 있습니까?

EOF는 파일 끝을 의미합니다.

이 경우 "EOF 트리거링"은 대략 "프로그램에서 더 이상 입력이 전송되지 않는다는 것을 인식하게 함"을 의미합니다.

이 경우 getchar()문자를 읽지 않으면 음수가 반환되므로 실행이 종료됩니다.

그러나 이것은 특정 프로그램에만 적용되는 것이 아니라 다양한 도구에 적용됩니다.

일반적으로 "트리거 EOF"는 마지막 입력 플러시 직후에 CTRL+ D키를 사용하여 수행 할 수 있습니다 (예 : 빈 입력을 전송).

예를 들면 다음과 cat같습니다.

% cat >file # Hit ENTER
foo # Hit ENTER and CTRL+D
% 

CTRL+를 칠 때 후드 아래에서 일어나는 일은 D마지막 입력 플러시 이후 입력 된 입력이 플러시된다는 것입니다. 이것이 빈 입력 인 경우 read()프로그램의 STDIN에서 호출 된 syscall은 ( GNU C 라이브러리에서) 음수를 리턴하며 0, 이는 EOF 1 로 해석됩니다 .getchar()-1


1- https : //stackoverflow.com/a/1516177/4316166


2
쉼표 구분이 같은 줄에 있으면 바인딩되지 않으므로 컴파일이 작동합니다. 그 외에 EOF에 대한 훌륭한 설명 :)
Paulius Šukys

@ PauliusŠukys Huh, 네 말이 맞아. 내 C는 조금 녹슬었다. :)
kos

1
iirc EOF는 표준에 따라 -1로 정의 되지 않았습니다 . 그것은 예를 들어 glibc에서 일어나는 일입니다.
larkey


1
EOF는 '빈 입력'을 보내는 것으로 구성되어 있지 않으며 인용하는 SO 답변은 달리 언급하지 않습니다. 대역 외 신호입니다. 터미널의 경우 Ctrl / d를 입력하여 전송합니다.
user207421

4

TL; DR : EOF는 문자가 아니며 입력 읽기 기능의 음수 리턴을 평가하는 데 사용되는 매크로입니다. Ctrl+ D를 사용 하여 EOT문자 를 보내면 함수가 반환됩니다.-1

모든 프로그래머는 RTFM을해야합니다

Harbison and Steele, 4th ed의 "CA Reference Manual"을 참조하십시오. 1995 년, 317 페이지에서 :

음의 정수 EOF는 "실제 문자"의 인코딩이 아닌 값입니다. . . 예를 들어 fget (섹션 15.6) 읽을 "실제 문자"가 없기 때문에 파일 끝에서 EOF를 반환합니다 .

본질적 EOF으로 문자가 아니라 를 나타 내기 위해 구현 된 정수 값 입니다. 따라서 kos의 답변은 가능한 한 정확하지만 "빈"입력을받는 것이 아닙니다. 중요한 점은 여기서 EOF는 실제 문자를 나타내지 않고 반환 값 ( ) 비교 의 역할을한다는 것 입니다. 다음을 지원합니다.stdio.h-1getchar()man getchar

반품 가치

fgetc (), getc () 및 getchar ()는 파일 또는 오류 끝에 int 또는 EOF에 부호없는 문자 캐스트로 읽은 문자를 리턴합니다.

gets () 및 fgets ()는 성공하면 s를 반환하고 오류가 발생하거나 문자를 읽지 않은 상태에서 파일 끝이 발생하면 NULL을 반환합니다.

ungetc ()는 성공하면 c를, 에러이면 EOF를 반환합니다.

while루프를 고려하십시오. 기본 목적은 대괄호의 조건이 true 인 경우 조치를 반복 하는 것입니다 . 다시 봐요:

while ((c = getchar ()) != EOF)

기본적으로 c = getchar()성공적인 코드를 반환 하면 계속해서 작업을 수행 합니다 ( 0또는 이상; 일반적으로 성공적인 명령을 실행 echo $?한 다음 실패 echo $?하고 반환하는 숫자를 확인하십시오). 따라서 문자를 성공적으로 가져오고 C에 요청하면 반환 된 상태 코드는 0이고 실패는 -1입니다. EOF로 정의됩니다 -1. 따라서 조건이 -1 == -1발생하면 루프가 중지됩니다. 그리고 언제 일어날까요? 더 이상 얻을 캐릭터가 없으면 c = getchar()실패합니다. 당신은 쓸 수 있고 while ((c = getchar ()) != -1)여전히 작동합니다

또한 실제 코드로 돌아가 봅시다. stdio.h

/* End of file character.
   Some things throughout the library rely on this being -1.  */
#ifndef EOF
# define EOF (-1)
#endif

ASCII 코드 및 EOT

그러나 EOF 문자는 실제 문자는 아니지만 EOTASCII 10 진수 값이 04 인 (End of Transmission) 문자가 있습니다. Ctrl+ D바로 가기에 연결됩니다 (메타 문자로도 ^D표시됨). 컴퓨터가 전화 연결을 제어하는 ​​데 사용되었을 때 데이터 스트림이 닫히는 것을 의미하는 데 사용되는 전송 끝점은 "전송 끝"이라는 이름입니다.

따라서 ascii 값을 프로그램에 보낼 수 있습니다 $'\04'. EOT는 다음과 같습니다.

skolodya@ubuntu:$ ./a.out  <<< "a,b,c $'\04'"                                  
digits = 1 0 0 0 1 0 0 0 0 0, white space = 2, other = 9

따라서 존재한다고 말할 수는 있지만 인쇄 할 수는 없습니다.

사이드 노트

우리는 과거 컴퓨터가 다재다능하지 않았다는 사실을 종종 잊습니다. 디자이너는 모든 키보드 키를 사용할 수 있어야합니다. 따라서 EOTCtrlD를 사용하여 문자를 보내는 것은 대문자 A, ShiftA를 입력하는 것과 달리 여전히 "문자를 보내는"것입니다. 따라서 EOT는 사용자가 제공한다는 의미에서 실제 문자이며 컴퓨터로 읽을 수 있지만 (인쇄 할 수는 없지만 사람이 볼 수는 없지만) 컴퓨터 메모리에 존재합니다.

바이트 사령관의 의견

/ dev / null에서 읽으려고하면 EOF도 반환해야합니까? 아니면 내가 무엇을 얻습니까?

그렇습니다. /dev/null실제로 읽을 문자가 없으므로 코드 c = getchar()를 반환 -1하고 프로그램이 즉시 종료됩니다. 다시 명령은 EOF를 반환하지 않습니다. EOF는 -1과 동일한 상수 변수이며 getchar 함수의 리턴 코드를 비교하는 데 사용됩니다 . EOF문자로 존재하지 않는 내부의 정적 값 stdio.h입니다.

데모:

# cat /dev/null shows there's no readable chars
DIR:/xieerqi
skolodya@ubuntu:$ cat /dev/null | cat -A        

# Bellow is simple program that will open /dev/null for reading. Note the use of literal -1                                   
   DIR:/xieerqi
skolodya@ubuntu:$ cat readNull.c                                               
#include<stdio.h>

void main()
{
   char c;
    FILE *file;
    file = fopen("/dev/null", "r");

    if (file) 
    {
    printf ("Before while loop\n");
        while ((c = getc(file)) != -1)
            putchar(c);
    printf("After while loop\n"); 
    fclose(file);
    }
}

DIR:/xieerqi
skolodya@ubuntu:$ gcc readNull.c -o readNull                                   

DIR:/xieerqi
skolodya@ubuntu:$ ./readNull
Before while loop
After while loop

관에 또 다른 못

때로는 EOF가 다음과 같은 코드를 가진 문자임을 증명하려고 시도합니다.

#include <stdio.h>
int main(void)
{
    printf("%c", EOF);
    return 0;
}

문제는 char 데이터 유형이 부호있는 값이거나 부호없는 값 일 수 있다는 것입니다. 또한 주소 지정이 가능한 가장 작은 데이터 유형이므로 메모리가 제한된 마이크로 컨트롤러에서 매우 유용합니다. 따라서 선언 int foo = 25;하는 대신 작은 메모리 char foo = 25;또는 이와 유사한 것을 가진 마이크로 컨트롤러에서 보는 것이 일반적 입니다. 또한 문자는 부호가 있거나 부호가 없을 수 있습니다 .

다음과 같은 프로그램으로 크기를 바이트 단위로 확인할 수 있습니다.

#include <stdio.h>
int main(void)
{
    printf("Size of int: %lu\n",sizeof(int));
    printf("Sieze of char: %lu\n",sizeof(char));
    //printf("%s", EOF);
    return 0;
}

skolodya@ubuntu:$ ./EOF                                                        
Size of int: 4
Sieze of char: 1

요점은 정확히 무엇입니까? 요점은 EOF가 -1로 정의되어 있지만 char 데이터 유형은 정수 값을 인쇄 할 수 있다는 것 입니다.

확인 . . .char를 문자열로 인쇄하려고하면 어떻게됩니까?

#include <stdio.h>
int main(void)
{
    printf("%s", EOF);
    return 0;
}

분명히 오류이지만 그럼에도 불구하고 오류는 우리에게 흥미로운 것을 알려줍니다.

skolodya @ ubuntu : $ gcc EOF.c -o EOF
EOF.c : 'main'함수에서 : EOF.c : 4 : 5 : 경고 : '% s'형식은 'char *'유형의 인수를 예상 하지만 인수 2에는 'int'형식 [-Wformat =] printf ( "% s", EOF);

16 진수 값

16 진수 값으로 EOF를 인쇄 FFFFFFFF하면 16 비트 (8 바이트) 값이 2로 칭찬 -1됩니다.

#include <stdio.h>
int main(void)
{
    printf("This is EOF: %X\n", EOF);
    printf("This is Z: %X\n",'Z');
    return 0;
}

산출:

DIR:/xieerqi
skolodya@ubuntu:$ ./EOF                                                        
This is EOF: FFFFFFFF
This is Z: 5A

다음 코드에서 또 다른 궁금한 사항이 발생합니다.

#include <stdio.h>
int main(void)
{
   char c;
   if (c = getchar())
    printf ("%x",c);
    return 0;
}

Shift+를 누르면 AASCII 테이블에서와 똑같이 16 진수 값 41을 얻습니다. 그러나 Ctrl+의 D경우 ffffffff에는 다시 getchar()저장된 값이 c있습니다.

DIR:/xieerqi
skolodya@ubuntu:$ gcc  EOF.c -o ASDF.asdf                                      

DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf                                                  
A
41
DIR:/xieerqi
skolodya@ubuntu:$ ./ASDF.asdf                                                  
ffffffff

다른 언어를 참조하십시오

다른 언어는 매크로와 비교하지 않고 함수 종료 상태를 평가하는 작업을 수행하므로이 혼동을 피하십시오. Java에서 파일을 어떻게 읽습니까?

    File inputFile  = new File (filename);
    Scanner readFile = new Scanner(inputFile);
    while (readFile.hasNext())
        { //more code bellow  }

파이썬은 어떻습니까?

with open("/etc/passwd") as file:
     for line in file:
          print line

요점은 실제로 어떤 시점에서 캐릭터가 어떻게 보내지 는가입니다.
kos

EOF 캐릭터는 실제 캐릭터가 아니기 때문에 번역에서 잃어버린 것 같습니다. 그러나 EOT는 실제 아스키 캐릭터입니다. 그림을 이동 !
Sergiy Kolodyazhnyy 2012 년

1
에서 읽으려고 /dev/null하면 EOF도 반환해야합니까? 아니면 내가 무엇을 얻습니까?
바이트 사령관

@ByteCommander는 알아낼 수 있습니다. cat / dev / null | 고양이 -A.
Sergiy Kolodyazhnyy

@ByteCommander 님이 댓글을 올리는 섹션을 추가했습니다
Sergiy Kolodyazhnyy 2012 년

2

EOF파일의 끝을 나타냅니다 . 다음 기호를 트리거하는 방법을 모르지만 파일을 파이핑하여 다음 프로그램을 실행할 수 있습니다.이 파일은 EOF 신호를 마지막에 보냅니다 .

echo "Some sample text" | ./a.out

a.out컴파일 된 소스는 어디에 있습니까


1
이 문제를 이미 상향 조정했지만 EOF는 문자가 아닙니다. 나는 일반적으로 인쇄 할 수없는 문자를 입력하는 방법 인 CTRL 키 입력을 통해 신호를 보낸다는 사실에서 오해가 발생한다고 생각합니다. 실제로 발생하는 모든 것을 이해함에 따라 모든 입력이 플러시되고 비워 질 입력 read()(syscall)이 반환 0되면 EOF로 해석됩니다. stackoverflow.com/a/1516177/4316166
kos

@ kos, 당신 말이 맞아, 결국 신호입니다.
Paulius Šukys
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.