문제

나는 줄 바꿈과 기타 다양한 문자를 포함할 수 있는 두 개의 문자열을 읽는 프로그램을 작성하고 있습니다.따라서 문자열을 끝내기 위해 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에 인쇄합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top