scanf ()는 버퍼에 새 줄 문자를 남깁니다.


87

다음 프로그램이 있습니다.

int main(int argc, char *argv[])
{
  int a, b;
  char c1, c2;
  printf("Enter something: ");
  scanf("%d",&a); // line 1
  printf("Enter other something: ");
  scanf("%d", &b); // line 2

  printf("Enter a char: ");
  scanf("%c",&c1); // line 3
  printf("Enter another char: ");
  scanf("%c", &c2); // line 4

  printf("Done"); // line 5

  system("PAUSE");

  return 0;
}

내가 C 책을 읽었을 때 저자는 scanf()버퍼에 줄 바꿈 문자 를 남겼으므로 프로그램은 사용자가 데이터를 입력하기 위해 줄 4에서 멈추지 않고 새 줄 문자를 c2에 저장하고 다음으로 이동합니다. 5 행.

맞습니까?

그러나 이것은 char데이터 유형 에서만 발생 합니까? int1, 2, 3 행에서 와 같이 데이터 유형에 대해이 문제를 보지 않았기 때문입니다. 맞습니까?


단일 문자를 fflush(stdin)호출하기 전에 사용할 수있는 경우가 있습니다 scanf(). 장단점 및 해당 방법에 대한 대안에 대한 논의를 보려면 사용fflush(stdin) 을 읽어보십시오 (Windows에서 어느 정도 작동하고 대부분의 다른 곳에서는 작동하지 않음).
Jonathan Leffler

어떤 책을 언급하고 있는지 알려주세요.?
surya kiran

답변:


78

scanf()함수는 문자 이외의 변환을 구문 분석하기 전에 자동으로 선행 공백을 건너 뜁니다. 문자 형식 (주로 %c, 스캔 세트 %[…]— 및 %n)은 예외입니다. 공백을 건너 뛰지 않습니다.

" %c"선택적 공백을 건너 뛰려면 선행 공백과 함께 사용하십시오 . scanf()형식 문자열 에 후행 공백을 사용하지 마십시오 .

이것은 여전히 ​​입력 스트림에 남아있는 후행 공백을 사용하지 않으며 행 끝까지도 사용하지 않으므로 동일한 입력 스트림을 사용 getchar()하거나 사용하는 경우에도주의하십시오 fgets(). 우리는 변환 전에 공백을 건너 뛰도록 scanf를 받고 %d있습니다.


리터럴 텍스트와 같이 변환 이외의 공백이 아닌 "지시문"( POSIX scanf 용어 사용 ) scanf("order = %d", &order);은 공백도 건너 뛰지 않습니다. 리터럴 order은 읽을 다음 문자와 일치해야합니다.

따라서 " order = %d"이전 줄에서 줄 바꿈을 건너 뛰고 싶지만 여전히이 질문과 같이 고정 문자열에 대한 리터럴 일치가 필요한 경우 거기를 원할 것입니다 .


7
%c, %n, %[]선두 공백을 소모하지 않는 3 개 지정된 기대합니다.
chux - 분석 재개 모니카

@chux 그래서 다른 경우에 scanf는 버퍼에서 이전에 모든 공백을 지우거나 입력에 대해 무시하지만 여전히 거기에 있습니까?
Suraj Jain

@SurajJain 예,
chux-Monica 복원

3
보기 에 빈 후행 scanf()형식 문자열scanf()내가 한 번만 물어 기대하면서 입력을 두 번 묻는 형식 문자열에 후행 공백에 대한 설명. 그것은 나쁜 생각입니다. 인간의 상호 작용을 기대한다면 놀랍게도 나쁘고 프로그램 상호 작용에는 좋지 않습니다.
Jonathan Leffler

31

사용 scanf(" %c", &c2);. 이것은 당신의 문제를 해결할 것입니다.


7

여기 에서 얻은 또 다른 옵션 은 할당 억제 옵션 을 사용하여 개행을 읽고 버리는 입니다. 이를 위해, 우리는 단지 사이 별표 문자 읽기 형식을 넣어 %c:

scanf("%d%*c",&a); // line 1
scanf("%c%*c",&c1); // line 3

scanf 그런 다음 다음 문자 (즉, 개행)를 읽지 만 포인터에 할당하지 않습니다.

그러나 결국 에는 FAQ의 마지막 옵션을 두 번째로하겠습니다 .

또는 요구 사항에 따라 scanf () / getchar ()를 잊어 버리고 fgets ()를 사용하여 사용자로부터 텍스트 줄을 가져와 직접 구문 분석 할 수도 있습니다.


2
이 기술의 문제점은 사용자가 a공백을 입력 한 다음 개행을 입력하면 억제 된 문자 변환이 공백을 읽고 여전히 개행을 남긴다는 것입니다. supercalifragilisticexpialidocious예상 할 때 사용자가 입력 하면 처리 할 a추가 문자가 많이 있습니다. 후행 억제 된 변환이 성공했는지 여부도 알 수 없습니다 scanf(). 에서 반환 된 값에 포함되지 않습니다 .
Jonathan Leffler

3

getchar()두 번째 호출 전에 사용하십시오 scanf().

scanf("%c", &c1);
getchar();  // <== remove newline
scanf("%c", &c2);

1
이것은 사용자가 아무것도 입력하지 않았다면 작동합니다. 예를 들어 후행 공백입니다. 그러나 다음 줄 바꿈으로 스캔하는 루프만큼 좋지 않습니다 : int c; while ((c = getchar()) != EOF && c != '\n') ;(주석에없는 경우 세 줄에 걸쳐 작성 됨). 종종 충분합니다. 그것은 절대 안전하지 않습니다 (그리고 바보들은 물건을 부수는 것에 대해 매우 영리하다는 것을 기억해야합니다).
Jonathan Leffler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.