이 글에서는 C 언어에서 주로 사용되는 입력 함수인 `scanf`, `gets`, 그리고 `fgets`의 차이점과 사용법에 대해 알아보겠습니다.
scanf
char str[100];
int num;
printf("문자열을 입력하세요: ");
scanf("%s", str); // 예를 들어 "hello world" 입력
printf("숫자를 입력하세요: ");
scanf("%d", &num); // 예를 들어, 42 입력
printf("입력된 문자열: %s\n", str); // 출력: "입력된 문자열: hello"
printf("입력된 숫자: %d\n", num); // 출력: "입력된 숫자: 42"
이 코드에서는 scanf로 입력 받은 문자열은 공백을 기준으로 구분되므로, "hello world"를 입력하면 "hello"만 출력됩니다.
scanf 함수는 기본적으로 공백 문자를 기준으로 입력을 구분합니다. 만약 문자열 입력이 공백을 포함하는 경우, `scanf` 함수는 공백 이전까지만 읽어 들입니다. 또한, `scanf` 함수가 처리할 형식지정자를 사용하여 다양한 자료형의 입력값을 제어할 수 있습니다.
gets
char str[100];
printf("문자열을 입력하세요: ");
gets(str); // 예를 들어, "hello world" 입력
printf("입력된 문자열: %s\n", str); // 출력: "입력된 문자열: hello world"
gets 함수는 문자열을 공백을 포함하여 한 줄 전체를 입력 받습니다. 이 코드에서는 "hello world"를 입력하면 "hello world"가 출력됩니다.
하지만, `gets` 함수는 입력 받는 문자열의 길이를 확인하지 않아서, 버퍼 오버플로우 문제가 발생할 수 있습니다. 이 때문에 보안상의 이유로 `gets` 함수는 비추천됩니다.
fgets
char str[100];
printf("문자열을 입력하세요: ");
fgets(str, sizeof(str), stdin); // 예를 들어, "hello world" 입력
printf("입력된 문자열: %s", str); // 출력: "입력된 문자열: hello world\n"
fgets 함수는 gets 함수의 안전한 버전으로, 문자열 입력과 길이 상한선을 함께 입력받아 버퍼 오버플로우 문제를 방지합니다. fgets 함수는 한 줄 전체를 입력받을 수 있으며, 입력 받은 문자열 끝에 '\n' 문자(줄바꿈 문자)가 추가됩니다.
따라서, "hello world"를 입력하면 "hello world\n"이 출력됩니다. 출력 시엔 개행 문자가 함께 출력되어 줄바꿈이 됩니다.
fgets 버퍼사이즈 지정
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 200
int main() {
char name[BUFFER_SIZE];
printf("이름을 입력하세요: ");
fgets(name, BUFFER_SIZE, stdin);
printf("%s님입니다.\n", name);
return 0;
}
이 코드에서는 #define을 사용하여 BUFFER_SIZE를 200으로 정의하고 있기 때문에 sizeof(name) 대신 BUFFER_SIZE를 사용해도 됩니다.
scanf와 fgets함수 동시 사용시 발생하는 문제
#include <stdio.h>
#define BUFFER_SIZE 200
int main() {
int age;
char name[BUFFER_SIZE];
printf("나이를 입력하세요: ");
scanf("%d", &age);
printf("이름을 입력하세요: ");
fgets(name, BUFFER_SIZE, stdin);
printf("%s님의 나이는 %d살입니다.\n", name, age);
return 0;
}
사용자로부터 입력받을때 위의 예시처럼 scanf와 fgets를 함께 사용시 발생하는 문제인데 scanf함수를 사용하여 사용자의 나이까지는 입력받는데 문제가 없지만, fgets 함수가 호출될 때 입력 버퍼에는 이미 scanf에서 입력을 받은뒤 개행 문자(\n)가 남아 있기 때문에, 입력할수 없으며 입력된 이름이 출력되지 않고 빈 문자열이 출력됩니다.
입력 버퍼 비우기
while (getchar() != '\n'); //입력버퍼 비우기
이 문제를 해결하기 위해서는 getchar()함수를 사용하여 입력버퍼를 비우면 다음 입력 함수가 작동됩니다.
해당 함수를 사용하기위해선 <string.h>헤더를 상단에 선언해줘야합니다.
getchar 함수는 표준 입력 스트림(stdin)에서 문자를 하나씩 읽어들입니다. '\n'(개행 문자)가 나올 때까지 문자를 읽어들이면서 입력 버퍼에 있는 내용을 제거합니다.
버퍼 비운후 다시 입력받기
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 200
int main() {
int age;
char name[BUFFER_SIZE];
printf("나이를 입력하세요: ");
scanf("%d", &age);
while (getchar() != '\n'); //입력버퍼 비우기
printf("이름을 입력하세요: ");
fgets(name, BUFFER_SIZE, stdin);
printf("%s님의 나이는 %d살입니다.\n", name, age);
return 0;
}
이 코드에서는 getchar()함수를 사용하기 위해 상단 <string.h>헤더를 선언해주었고 scanf()함수로 사용자로부터 나이를 입력받은뒤 입력버퍼를 비워준다음 fgets()함수로 사용자의 이름을 입력받은뒤 결과를 정상적으로 출력해줍니다.
요약
요약하자면, scanf는 형식 지정자를 제공하지만 공백을 기준으로 입력을 구분합니다. gets는 문자열 전체를 입력받지만 버퍼 오버플로우의 문제가 있어 사용하지 않는 것이 좋습니다. fgets는 안전하게 문자열 전체를 입력받으며, 문자열 길이를 제어할 수 있습니다.