[C]gets & fgets
- gets함수는 문자열 출력함수입니다.
- fgets함수는 스트림에 문자열을 읽는 함수입니다.
1️⃣ 함수원형
< gets >
char *gets(char *str);
< fgets >
char *fgets(char *str, int num, FILE *stream);
2️⃣ 헤더파일, 반환값
- 헤더파일: <stdio.h>
반환값:
성공 실패 gets 읽어들인 문자열(str) NULL포인터 fgets 읽어들인 문자열(str) NULL포인터
3️⃣ 함수사용
(1) gets
#define BUFFER 256
int main(void)
{
char string[BUFFER];
char *result;
result = gets(string);
printf("%s\n", result);
}
(2) fgets
< test.txt내용 >
nice to meet you!
< fgets >
#define BUFFER 20
int main(void)
{
FILE *stream;
char string[BUFFER];
char *result;
stream = fopen("test.txt", "r");
result = fgets(string, BUFFER, stream);
printf("%s\n", result);
}
/*---출력---*/
Hello my name is ki
4️⃣ 특징 & 주의사항
gets, fgets
함수 모두 끝에 자동으로'\0'
문자를 넣어 줍니다.- gets함수는 매우 매우 위험한 함수입니다. 최신 헤더파일에서는 gets함수가 없습니다.
(C11에서는 아예 이 함수를 제거)(아래 자세한내용) fgets
함수 또한 두번째인자값이 첫번재인자의 크기보다 클경우 버퍼오버플로우가 일어납니다. 그렇기 때문에 위의 코드처럼 두번째인자를BUFFER
로 매크로형식으로 크기를 동일하게 작성하는 것도 한 방법입니다.fgets
함수는 ‘\n’개행문자까지 읽어들입니다.(아래 자세한내용)
5️⃣ 코드예시(특이케이스)
(1)< gets함수의 위험성 >
#define BUFFER 5
int main(void)
{
char sample[6] = "hello";
char string[BUFFER];
char *result;
printf("before sample: %s\n", sample);
result = gets(string);
printf("result: %s\n");
printf("after sample: %s\n", sample);
}
/*---입력값---*/
abcdefg
/*---출력값---*/
before sample: hello
result: abcdefg
after sample: fg
- 위의 코드처럼 다른메모리에 침범을 하게 됩니다.(보안상의 위험성이 크다)
- BUFFER의 크기를 조정한다고해서 해결할 문제가 아닙니다. (언제가는 버퍼오버플로우가 생김)
- 이러한 이유 때문에 gets함수는 절대로 사용하지 않는 것이 좋습니다.
(2)< '\n'도 읽어들이는 fgets함수 >
이 처럼 fgets함수는 새 줄을 만나서 끝났을 떄랑 아닐 떄를 구분해야 하기 때문에 ‘\n’문자까지도 읽어 드립니다. (새 줄을 만나지 않아도 반환될 수 있음)
int main(void)
{
char string[BUFFER]; //#define BUFFER 20
fgets(string, BUFFER, stdin); //입력 : "hello"
printf("< puts 함수결과 >\n");
puts(string);
printf("< printf 함수결과 >\n");
printf("%s", string);
}
/*---출력---*/
< puts 함수결과 >
hello
< printf 함수결과 >
hello
- fgets함수에서 stdin(입력스트림)형식으로 입력을 완료하기 위해서는 개행문자(\n)을 입력해야 합니다. 이때
fgets함수
는'\n'
까지 읽어드립니다. - 이때
puts함수
는 자동으로 ‘\n’을 문자끝에 출력해줍니다. 그렇기 때문에 fgets + puts 조합으로 사용할시 ‘\n’이 두번적용됩니다. - 결과적으로
fgets함수는 printf계열의 함수와 사용
하는 것이 어울립니다.
(3)< sscanf + fgets조합의 입력코드 >
#define BUFFER (4096)
#ifndef TRUE
#define TRUE (1)
#endif
int main(void)
{
char temp[BUFFER];
char result[BUFFER];
while (TRUE)
{
if (fgets(temp, BUFFER, stdin) == NULL)
{
clearerr(stdin);
break;
}
if (sscanf(temp, "%s", result) == 1)
printf("%s\n", result);
}
}
- 위험할 수 있는
scanf함수
를 대체할 수 있는 코드조합입니다. fgets함수
와sscanf
함수의 단점을 서로 보완했으며 매우 효과적인 코드조합입니다.( 자세한 내용은 scanf관련 POST에 있습니다 )