본문 바로가기
개인공부/C, C++

[C/C++] scanf의 작동원리

by BuyAndPray 2021. 1. 24.
반응형

scanf()는 사용자의 입력을 특정 형식(format string)에 맞춰 읽은 뒤 변수에 값을 저장한다. 이 형식(format string)에는 일반적인 문자(ex. a, b, c, 공백 등)나 변환 문자(conversion specification)가 들어갈 수 있는데 어떤 값이 들어가느냐에 따라 작동하는 방법이 다르다.

 

format string이 변환 문자로만 구성된 경우

아래와 같이 scanf의 format string이 변환 문자로만 구성된 경우를 살펴보겠다.

scanf("%d%f", &intValue, &floatValue);

이런 경우 scanf()는 다음과 같은 순서로 작동한다.

 

  1. 사용자로부터 들어온 input string(string type)을 format string과 왼쪽부터 비교한다.
  2. 제일 처음 시작되는 공백은 무시하고 input character를 하나씩 읽으며 변환 문자(%d, %f)와 비교한다.
  3. 해당 변환 문자가 input character를 읽을 수 있다면 다음 input character를 변환 문자와 비교.
    만약 해당 변환 문자가 input character를 읽을 수 없는 경우 다음 변환 문자와 input character를 비교(다음 변환 문자가 없을 경우 다음 scanf 함수가 호출될 때 비교)
  4. 해당 변환 문자가 읽을 수 없는 형식으로 input string이 들어오면 함수를 return(뒤에 위치한 나머지 변환 문자는 값을 읽을 수 없음)

그리고 %d(Integer type)와 %f(floating-point type)가 읽을 수 있는 형식은 아래와 같다.

 

  • Integer type
    • 첫 번째 문자로는 (숫자, +, -)만 가능하다
    • 그 이후로는 오직 숫자만 가능하다
  • Floating-point type
    • 첫 번째 문자가 (+, -)로 시작하는지 확인, 시작하면 읽음(꼭 시작할 필요는 없음)
    • 그 이후로는 (숫자, 소수점, 지수(e, E))만 가능하다

예를 들어 다음과 같은 scanf()가 있을 때 input으로 [1-20.3-4]가 들어오면 scanf는 다음과 같이 동작한다.

#include <stdio.h>

int main(int argc, char* argv[]) {
	int i1,i2;
	float f1,f2;
	
	scanf("%d%d%f%f", &i1, &i2, &f1, &f2); // 1-20.3-4
	
	printf("%d %d %.1f %.1f\n", i1, i2, f1, f2); //1 -20 0.3 -4.0
	
	return 0;
}

 

  1. input string의 제일 처음 값 [1]을 첫 번째 변환 문자 %d(i1에 해당)가 읽을 수 있는지 확인(가능) - 진행
  2. input string의 두 번째 값 [-]를 %d가 읽을 수 있는지 확인(%d는 오직 첫 번째로 들어온 [-]만 읽을 수 있고 이미 1이 들어온 상태이기 때문에 읽을 수 없음) - 읽지 않고 멈춤
  3. 두 번째 변환 문자 %d(i2에 해당)가 앞에서 읽지 못한 [-]를 읽을 수 있는지 확인(%d는 첫 번째 문자로 [-]를 읽을 수 있기에 가능) - 진행
  4. [2]를 읽을 수 있는지 학인(가능) - 진행
  5. [0]을 읽을 수 있는지 확인(가능) - 진행
  6. [.]을 읽을 수 있는지 확인(불가능) - 읽지 않고 멈춤
  7. 세 번째 변환 문자 %f(f1에 해당)가 [.]을 읽을 수 있는지 확인(가능) - 진행
  8. [3]을 읽을 수 있는지 확인(가능) - 진행
  9. [-]를 읽을 수 있는지 확인(불가능) - 읽지 않고 멈춤
  10. 네 번째 변환 문자 %f(f2에 해당)가 [-]를 읽을 수 있는지 확인(가능) - 진행
  11. [4]를 읽을 수 있는지 확인(가능) - 진행
  12. 제일 마지막 줄 바꿈 [\n]을 읽을 수 있는지 확인(불가능) - 읽지 않고 멈춤

위와 같은 과정을 통해 (i1, i2, f1, f2)는 각각 (1, -20, 0.3, -4)의 값을 가지고 마지막 줄 바꿈 '\n'은 읽어지지 않은 채 input buffer에 남아 다음 scanf가 실행될 때 처리된다.

 

format string에 일반 문자가 포함되어 있는 경우

공백이 포함되어 있는 경우

format string에 한 개 또는 여러 개의 공백이 포함되어 있는 경우 input character와 format string 공백을 비교할 때 공백이 아닌 문자가 들어올 때까지 계속 읽는다. 이때 input charater의 공백의 개수는 상관이 없다. 즉 format string에 공백이 있는 경우 input string 상의 0~무한개까지의 공백과 매칭이 된다.

 

아래와 같은 경우 입력으로 들어오는 1과 -2 사이 공백이 몇 개든 상관이 없다.

#include <stdio.h>

int main(int argc, char* argv[]) {
	int i1,i2;
	
	scanf("%d %d", &i1, &i2); 

	printf("%d %d\n", i1, i2); 
	
	return 0;
}

/*
Result

입력
1-2
출력
1 -2

입력
1 -2
출력
1 -2

입력
1                                                      -2
출력
1 -2

입력
1
-2
출력
1 -2

*/

 

공백 이외의 문자가 포함되어 있는 경우

format string에 공백 이외의 문자가 포함되어 있는 경우 input character와 비교할 때 fomat string 문자가 input character와 일치하면 입력 과정을 계속 진행시키고 없으면 scanf를 종료시킨다.

 

#include <stdio.h>

int main(int argc, char* argv[]) {
	int i1, i2 = -1;
	
	scanf("%d/%d", &i1, &i2); 

	printf("%d %d\n", i1, i2); 
	
	return 0;
}

/*
Result

입력
1/2
출력
1 2

입력
1 2
출력
1 -1 // i2는 읽어지지 않고 종료됨

입력
1%2
출력
1 -1 // i2는 읽어지지 않고 종료됨

*/

 

출처

반응형

댓글