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.