문제
나는 줄 바꿈과 기타 다양한 문자를 포함할 수 있는 두 개의 문자열을 읽는 프로그램을 작성하고 있습니다.따라서 문자열을 끝내기 위해 EOF(Ctrl-Z 또는 Ctrl-D)를 사용하고 있습니다.
이것은 첫 번째 변수에서는 잘 작동하지만 두 번째 변수에서는 분명히 입력 버퍼에 뭔가가 걸려 있고 사용자가 아무 것도 입력할 수 없기 때문에 문제가 있는 것 같습니다.
버퍼를 청소하려고했습니다. while (getchar() != '\n');
몇 가지 유사한 변형이 있지만 아무것도 도움이 되지 않는 것 같습니다.모든 정리 시도로 인해 무한 루프가 발생했으며 정리 없이는 두 번째 변수를 추가하는 것이 불가능합니다.
두 변수의 문자는 다음과 같은 루프에서 읽혀집니다. while((c = getchar()) != EOF)
, 이는 내가 버퍼에 갇힌 것이 EOF임을 의미합니다.아니면 다른 방식으로 프로그램의 동작에 영향을 미치나요?내가 사용하고 있는 논리에 문제가 있나요?
나는 몇 시간 동안 이것으로 어려움을 겪은 후에 약간 필사적이기 시작했습니다.
[편집하다:아래에 코드 추가]
[편집 2:결국에는clearerr()이 이 EOF 솔루션을 작동하게 만드는 것 같습니다.
리눅스에서 의도한 대로 원래대로 돌아가는 것 같은데, 어제 윈도우에서 시도해 봤습니다.]
암호:
#include <stdio.h>
#include <string.h>
int main(void)
{
int x = 0;
int c;
char a[100];
char b[100];
printf("Enter a: ");
while((c = getchar()) != EOF)
{
a[x] = c;
x++;
}
a[x] = '\0';
x = 0;
/*while (getchar() != '\n'); - the non-working loop*/
printf("\nEnter b: ");
while((c = getchar()) != EOF)
{
b[x] = c;
x++;
}
b[x] = '\0';
printf("\n\nResults:\na: %s\n", a);
printf("b: %s\n", b);
return(0);
}
[편집 3:]
동적 메모리 문제:
내 프로그램은 100자보다 긴 문자열도 처리해야 합니다.원래는 동적 메모리 할당으로 이 문제를 해결하려고 했으나 위에서 설명한 무한 루프 및 메모리 관련 충돌 문제가 발생했을 때 이를 생략하고 char[100]으로 전환했습니다.
내가 시도한 것은 일반적으로 다음과 같았다고 생각합니다.
while((c = getchar()) != EOF)
{
a = malloc(sizeof(char));
a[x] = c;
x++;
}
그게 가능한(또는 합리적인) 방법인가요?여기서 처리되는 모든 문자에 대해 더 많은 메모리를 할당하려고 합니다.개별적으로.그런 코드(이 예제에는 아마도 구문 오류가 있을 수 있음)를 사용하면 충돌이 발생했기 때문에 malloc이 여기에서 올바른 함수가 아닐 수도 있고 잘못 시도한 것 같습니다.심지어 가능하다고 가정해보자.
해결책
터미널에서 EOF를받은 후 추가 데이터를받지 못합니다. 입력을 미지로 연결하는 방법은 없습니다. 파일의 끝은 끝입니다.
따라서 각 변수가 별도의 줄에 입력되었고 사용자가 EOF 대신 ENTER를 누르도록 정의해야합니다. 사용자가 실제로 EOF를 입력했으며 다른 것을 볼 수 없기 때문에 EOF를 받았는지 여부를 확인해야합니다.이 경우 루프에서 벗어나 오류 메시지를 인쇄해야합니다.
다른 팁
EOF
그렇지 않습니다 캐릭터 - 입력 함수가 반환하여 상태, 해당 입력 스트림의 "파일 끝"에 도달했습니다. Martin v. Löwis가 말했듯이, "파일 끝"조건이 발생하면 해당 스트림에서 더 이상 입력을 사용할 수 없음을 의미합니다.
혼란은 다음과 같습니다.
- 많은 터미널 유형은 "파일"이 대화 형 터미널 (예 : Ctrl-Z 또는 Ctrl-D) 일 때 "파일의 끝"을 신호하는 특수 키 스트로크를 인식합니다. 그리고
- 그만큼
EOF
값은getchar()
기능의 가족.
입력을 분리하려면 실제 문자 값을 사용해야합니다 - ASCII NUL 문자 '\0'
입력 자체 내에서 유효한 값으로 나타날 수없는 경우 좋은 선택 일 수 있습니다.
Linux 상자에서 코드를 실행합니다. 결과는 다음과 같습니다.
Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>
Results:
a: qwer
asdf
b: 123
456
터미널 입력 버퍼가 비어 있지 않기 때문에 2 개의 Ctrl-D가 필요했습니다.
널 문자('\0'
) 변수를 분리합니다.다양한 UNIX 도구(예: find
)은 이러한 방식으로 출력 항목을 분리할 수 있으며 이는 상당히 표준적인 방법임을 시사합니다.
이것의 또 다른 장점은 스트림을 단일 버퍼로 읽은 다음 배열을 만들 수 있다는 것입니다. char*
s는 개별 문자열을 가리키며 각 문자열은 올바르게 표시됩니다. '\0'
-버퍼의 어떤 것도 수동으로 변경할 필요 없이 종료됩니다.이는 메모리 할당 오버헤드가 적다는 것을 의미하며, 읽고 있는 변수 수에 따라 프로그램 실행 속도가 눈에 띄게 빨라질 수 있습니다.물론 이는 모든 변수를 동시에 메모리에 보관해야 하는 경우에만 필요합니다. 한 번에 하나씩 처리하는 경우에는 이러한 특별한 이점을 얻을 수 없습니다.
당신이 시도하는 것은 EOF에서 근본적으로 불가능합니다.
어떤면에서는 하나처럼 행동하지만 EOF는 스트림의 캐릭터가 아니라 환경 정의 된 매크로입니다. 끝 스트림의. 나는 당신의 코드를 보지 못했지만 당신이하고있는 당신이 모이는 것입니다.
while ((c=getchar()) != EOF) {
// do something
}
while ((c=getchar()) != EOF) {
// do something else
}
EOF 문자를 처음 입력하면 첫 번째 문자열을 끝내기 위해 스트림이 돌이킬 수 없을 정도로 닫힙니다. 즉, 스트림의 상태는 그것이 닫혔다는 것입니다.
따라서, 두 번째 While 루프의 내용은 결코 실행되지 않습니다.
EOF의 입력을 중지하는 대신 - 캐릭터가 아닙니다 - Enter에서 중지하십시오.
while((c = getchar()) != '\n')
{
if (c == EOF) /* oops, something wrong, input terminated too soon! */;
a[x] = c;
x++;
}
EOF는 입력이 종료 된 신호입니다. 사용자의 모든 입력이 ' n'으로 끝나는 것을 거의 보장합니다. 이것이 사용자 유형의 마지막 키입니다 !!!
편집 : 여전히 Ctrl-D를 사용할 수 있습니다 clearerr()
입력 스트림을 재설정합니다.
#include <stdio.h>
int main(void) {
char a[100], b[100];
int c, k;
printf("Enter a: "); fflush(stdout);
k = 0;
while ((k < 100) && ((c = getchar()) != EOF)) {
a[k++] = c;
}
a[k] = 0;
clearerr(stdin);
printf("Enter b: "); fflush(stdout);
k = 0;
while ((k < 100) && ((c = getchar()) != EOF)) {
b[k++] = c;
}
b[k] = 0;
printf("a is [%s]; b is [%s]\n", a, b);
return 0;
}
$ ./a.out Enter a: two lines (Ctrl+D right after the next ENTER) Enter b: three lines now (ENTER + Ctrl+D) a is [two lines (Ctrl+D right after the next ENTER) ]; b is [three lines now (ENTER + Ctrl+D) ] $
프로그램에 NULL을 어떻게 입력합니까?
다음을 사용하여 -print0 함수를 구현할 수 있습니다.
putchar(0);
이것은 ascii nul 문자 ' 0'을 sdtout에 인쇄합니다.