Computer Science/Algorithm

[C언어] 표준 입력 함수, scanf() 함수의 오류 찾기

kyxxn 2023. 5. 31. 01:40
728x90

오류찾기

다음은 잘못된 코드이다. 왜 그런지 알아보자.

오류를 먼저 찾을 수 있는지 확인해 보고 아래 글을 읽기를 추천한다.

#include <stdio.h>

int main() {
	char arr[21] = "”; /* 모두 널로 초기화 */
	printf("최대 20문자 입력 가능\\n");
	printf("(Q 혹은 이 입력 시 종료)\\n");
	printf("---------------------\\n");
	
	for(int i=0; i<20; i++){
		printf("아무 키나 입력하세요 : ");
		scanf("%c", &arr[i]); 
		
		if(arr[i] == 'Q' || arr[i] == 'q') break;
	}

	printf("----------------------\\n");
	printf("%s", arr);
	
	return 0;
}

동생 공부 도와주다가 나름 흥미로운 걸 발견해서 오늘은 위 코드에 대해 공부해 볼 거다.

위 코드에서 scanf(” %c”, &arr[i]); 부분에 %c를 왜 한 칸 띄우고 적는지 안다면, 이번 게시물의 내용은 다 이해했다고 볼 수 있다.

 

scanf() 함수의 원형은 다음과 같다.

#include <stdio.h>

int scanf(const char * restrict format, ...);

먼저 scanf() 함수는 C언어의 표준 입력 함수로, 사용자로부터 다양한 데이터를 다양한 서식에 맞춰 입력받을 수 있게 하는 역할을 한다.

scanf의 f는 formatted의 약자로, 서식화된 입력을 받는다는 의미이다.

입력받은 데이터를 어떤 서식으로 변환할 지 서식 지정자(format specifier)를 통해 직접 지정이 가능하다.

 

코드 살펴보기

 

문제의 코드를 살펴보겠다

char arr[21] = "”; /* 모두 널로 초기화 */

arr이라는 배열은 char를 데이터 형으로, 크기는 21개를 갖고 있다는 것을 선언과 동시에 널로 초기화해주었다.

for(int i=0; i<20; i++){
		printf("아무 키나 입력하세요 : ");
		scanf("%c", &arr[i]); // 이 문장이 이 글을 적게 된 이유이다.
		
		if(arr[i] == 'Q' || arr[i] == 'q') break;
	}

for i ← 0 to 19로, 20번만 반복한다.

char 배열로, 문자열을 저장하니 마지막 인덱스는 널 값을 남겨두려고 20번만 반복하고 있다.

scanf() 함수 동작원리

위 코드를 이해하기 앞서 scanf() 함수 동작원리에 대해 알아보겠다.

scanf 함수는 사용자로부터 입력을 받을 때, 공백 문자(스페이스, 탭, 개행 등)를 구분자로 사용한다.

즉, ”%c”로 문자를 입력받을 때, 버퍼에는 \n이 남아있어서 이것 또한 문자로 인식될 수 있다는 것이다.

 

예를 하나 들어보겠다.

사용자가 “A”를 입력하면, “A”만 입력이 되어야 하지만, 사용자가 “A”하고 엔터를 누르면 버퍼에 개행 문자 ‘\n’이 남아있게 된다. 이후 “%c”로 문자를 입력 받을 때, 버퍼에 있는 문자를 우선적으로 읽는 특징에 의해 사용자가 원치 않는 동작이 발생할 수 있다.

그러니까 “%c”로 20번이나 배열에 값을 입력 받으니 이 코드는 개행 문자가 계속 남아있을 수 밖에 없다.

 

이러한 문제를 방지하기 위해 “%c” 앞에 공백을 한 칸 띄우면

scanf 함수는 버퍼에서 공백 문자를 스킵하고, 그 다음 실제 문자를 입력받게 된다.

 

따라서 아래와 같이 코드를 작성해야 한다.

#include <stdio.h>

int main() {
	char arr[21] = "”; /* 모두 널로 초기화 */
	printf("최대 20문자 입력 가능\\n");
	printf("(Q 혹은 이 입력 시 종료)\\n");
	printf("---------------------\\n");
	
	for(int i=0; i<20; i++){
		printf("아무 키나 입력하세요 : ");
		scanf(" %c", &arr[i]); // 이번 글의 핵심이다.
		
		if(arr[i] == 'Q' || arr[i] == 'q') break;
	}

	printf("----------------------\\n");
	printf("%s", arr);
	
	return 0;
}

정리

scanf를 사용하면 개행 문자('\n')를 처리하지 않는다.

즉, scanf로 여러 줄의 문자 입력을 받을 경우 첫 번째 문자를 띄우고 사용하면 된다.