본문 바로가기

C언어

Chapter 6. scanf()와 fgets()

Chapter 6. scanf()와fgets()

scanf()는 숫자를 받아들일 때에만 fgets()는 문자열을 받아들일 때에만 사용한다.

intscanf(constchar *format, ...);

첫번째 인자는 문자열 포인터이고 두번째 인자는"가변 인자" 이다.

6_1.c

#include <stdio.h>
#include <stdlib.h>

main()
{
char *name;

name = (char *)malloc(sizeof(char) * 20);

printf("Input your name : ");
scanf("%s", name);
puts(name);
}

gcc -o 6_1 6_1.c
./6_1
Input your name : Park Nara

Park

다른 문자열도 출력하고 싶다면 char 변수를 각각 선언하고 scanf("%s %s%s", name1, name2, name3); 와 같이 이용해야 된다.

3단어 이상 입력하고 싶다면?

scanf()는 문자열과 별로 친하지 않은 함수이다.

문자열을 입력받고 출력할 때는 되도록이면 fgets()를사용하는 것이 좋다.

gets()는 흔히 시스템 프로그램의 세계에서"저주 받은함수"로 알려져 있다.버퍼 오버플로우를 검사하지 않으므로 상당히 위험한 함수이다.

6_2.c

#include <stdio.h>
#include <stdlib.h>

main()
{
char *name;

name = (char *)malloc(sizeof(char) * 10);

gets(name);
puts(name);
}

gcc -o 6_2 6_2.c
./6_2
Jung Jae Une
Jung Jae Une

"Jung Jae Une"이라는 문자열의 길이는 12이며 Null 문자까지 포함하면 13byte의 메모리 영역이 필요하다.

malloc() 함수로 10byte를 할당했기 때문에"Une"라는 글자는보장 받을 수 없게 된다. 운이 좋으면 위와 같이 나올 수 있다.

올바른프로그램이라면 9byte만 받아들이도록 해야한다.

6_3.c

#include <stdio.h>
#include <stdlib.h>

main()
{
char *name;

name = (char *)malloc(sizeof(char) * 10);

fgets(name, 10, stdin);
puts(name);
}

gcc -o 6_3 6_3.c

./6_3
Jung Jae Une
Jung Jae

scanf()와 달리 fgets()는 개행 문자를 포함한다.

6_4.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

main()
{
char *name;
name = (char *)malloc(sizeof(char) * 10);
fgets(name, 10, stdin);

if(!strcmp(name, "archie"))
puts("welcome to archie");
else
puts("not archie");
putchar('\n');

printf("name : %d\n", strlen(name));
printf("archie : %d\n", strlen("archie"));

putchar('\n');

for(;*name;name++)

printf("%c : %d\n", *name, *name);

}

gcc -o6_46_4.c

./6_4
archie
not archie

name : 7
archie : 6

a : 97
r : 114
c : 99
h : 104
i : 105
e : 101

: 10

"archie"를 입력한 후 name이라는 변수의 문자열 길이를 출력해보니 7이라는 수치가 나왔는데

이것은 결국 name이라는 변수에 눈에 보이지 않는 문자가 하나 추가 되었다는 것을 알 수 있다.

보이지 않는 문자의 ASCII 값은 10이라는 것을 확인할 수 있으며이것은 바로 개행 문자(\n)이다.

fgets()를이용하여 문자열을 받아들이면 항상 개행 문자가 삽입되므로 제거하는 것이 좋다.

*(name+(strlen(name) - 1))= '\0';

*(name + (strlen(name) - 1)) = 0;

*(name+ (strlen(name)- 1)) =NULL;

name[strlen(name) - 1] ='\0';

(strlen(name)- 1)[name] = '\0';

'\0'은 널 문자를뜻하며 0과NULL은 널 포인터를뜻한다.

이것은 예전 시스템에서는 문제를 일으킬 수도 있지만 현재대다수의 컴파일러나 시스템에서는 문제를 일으키지 않는다.

문자열을 받아들일 때는 scanf()나 gets()보다는 fgets()를 사용하고 fgets()를 사용할 때는 가장 마지막 문자인 '\n'(개행 문자)의 처리를 잊지 말자.

'C언어' 카테고리의 다른 글

Chapter 4. 문자열과 포인터  (0) 2011.10.16
Chapter 5. 포인터의 포인터  (0) 2011.10.16
Chapter 2. 1차원 배열과 포인터  (0) 2011.10.16
Chapter 3. 2차원 배열과 포인터  (0) 2011.10.16
실행결과  (0) 2011.10.16