상세 컨텐츠

본문 제목

C언어) 입력 버퍼 비울 때, getchar() 사용 시 유의사항

c언어

by 빙하둘리 2022. 7. 14. 12:54

본문

728x90

이전에 입력 버퍼를 비워주기 위해 getchar()을 사용했었다.

실제로 입력 버퍼를 비우는데 getchar()을 쓰면 편한데, 잘 알고 넘어가야될 점이 있다.

 

getchar() 함수는 문자 하나를 읽어드리는 함수다.

다음과 같이 scanf 함수에 개행처리 \n를 해줬을 때, getchar();을 버퍼를 비우는 용도로 쓰면 안 된다.

scanf("%d\n", &N); // 개행 처리
char ch = getchar();
printf("getchar이 받아드린 값은 %d", ch);

char * str = malloc(sizeof(char) * 12);
scanf("%[^\n]s", str);
getchar();
printf("\n str is %s", str);

scanf 함수에 이미 개행처리가 되었기 때문에 사용자가 정수값 N을 입력하고 엔터를 쳐서 N 값을 저장한 다음, push를 입력한다고 하자. scanf 함수의 \n 때문에

push에서 p는 getchar()으로 받아들였다.

getchar으로 인해서 문자열 str은 p가 잘린 값 ush만을 받게 된다.

 

백준 2161에서, scanf 함수에 개행처리를 해준다면 다음과 같은 오류가 난다.

int N;
	scanf("%d\n", &N);
    //추후에 printf로 출력, scanf 사용 안함

프로그램 실행 시, 엔터를 아무리 눌러도 안 끝난다. 그래서 Ctrl + Z를 해주니 끝났다.

 

 

여기서 getchar()을 해서 버퍼를 비우려 했다. 엔터를 아무리 쳐도 종료가 안되는데, Ctrl+Z를 두번하니 종료가 되었다. getchar이 받는 값은 -1이다.

 

7 엔터하고 바로 s를 치면 getchar은 s를 받긴 받는다.

7 치고 엔터 엔터 엔터... 반응이 없어서 s를 누르니 종료 되어서 getchar은 s를 받았다고 한다.

아무래도 숫자 입력 후 엔터 치고 다른 문자를 치기를 기다리는데 계속 엔터가 들어와서 getchar은 아무것도 못 받았다 생각하는 것 같다. 그러고 s를 누르니 그제서야 getchar이 s를 받았다고 본다.

 

 

만약 scanf 함수를 개행처리를 안 하고 getchar을 한다면?

getchar은 Line Feed(아스키 코드 10)을 받는다.

int N;
scanf("%d", &N);
char ch=getchar(); //getchar 유무에 따라서 달라진다. //here getchar value??
char* str = malloc(sizeof(char) * 12);
printf("getchar이 받아드린 값은 %d\n", ch);
scanf("%[^\n]s", str);
getchar();
printf("\n str is %s", str);

getchar()은 엔터를 읽어드린다. 그래서 아스키코드 값이 10이 나온다.(Line Feed)

 

결과를 보고 비교를 하자.

scanf 함수에 \n을 넣어주나 안 넣어주나 숫자를 치고 엔터를 쳐야되는 것은 동일하다. Command 창에 문자열을 입력하는공간도 모두 둘째줄이다.  다만 getchar 함수가 무엇을 저장하는지에 따라 다르다.

scanf 함수에 개행 처리를 한 경우, getchar은 push에서 첫 글자 p를 받고,

scanf 함수에 개행 처리를 하지 않은 경우, getchar 함수는 개행 문자 \n을 받는다.  따라서 getchar은 아스키코드 10의 값을 가진 LF를 받은 것이다.

 

 

위 두번째 경우에는 scanf 함수를 두번 써서, 한번은 숫자를 받고 한번은 문자열을 받는데..

scanf 한 번 써서 숫자만 받으면 getchar이 필요 없다.

int N;
	scanf("%d", &N);

 

숫자 하나만 입력받는 2161번에서 scanf 함수에다 개행처리를  안 하고, getchar()을 안 해도

잘만 나온다. 아무래도 숫자 하나만 받으니, 숫자를 받고 버퍼를 비워줄 필요가 없어보인다.

 

물론, 다음과 같이 뒤에 getchar을 한다 해도 엔터를 getchar이 받는 것이기 때문에 괜찮다.

 

결론적으로 scanf를 한 번 쓸 때는 scanf("%d", &N);만 써도 된다.(그 뒤에 getchar을 써도 괜찮다.)

숫자 N만 받고 싶은데 scanf("%d\n", &N); getchar();을 하면 숫자 N 하나가 아닌 다른 값을 받아야 끝나서 주의해야 된다.

getchar() 함수가 scanf 함수로 값을 받고, 버퍼를 비우는데 유용하긴 하나 주의해서 사용해야 된다고 본다.

숫자 하나만 받는데 scanf("%d\n", &N);면 ctrl+Z로 종료해줘야 되는 문제점이 있다.

 

여러 개의 숫자, 문자를 받는 코드 예시는 다음과 같다.

int main(void)
{

    StackInit(&s1);
    StackInit(&s2);
    char str[100001]; //처음에는 10만개 문자!!
    int M;
    scanf("%s", str);
    getchar();
    int N=strlen(str); //문자열 길이는 N
    scanf("%d", &M); //명령어 개수
    getchar();
   
   FirstText(str, N);
   
   for(int k=0; k<M; k++)
   {
        char c1, c2;
        scanf("%c", &c1);
        getchar();
	    if (c1 == 'P')
	    {
		    scanf(" %c", &c2); //%c 앞에 공백을 포함해야된다. 특정문자 다음 스페이스와 c2를 둘 다 인식해야 되기 때문
            getchar();
		 //   printf("%c AND %c\n", c1, c2);
            SPush(&s1, c2);
	    }

scanf 함수에 \n을 안 넣어준 코드다. scanf 함수 사용 후에, getchar을 하면 잘 돌아간다.

scanf("%d", &N); getchar();

 

 

 

scanf 함수 일부에 \n을 넣어주고 getchar을 지워버리면 어떻게 동작할까?

scanf 함수의 \n이 개행처리를 해주고 바로 다음 scanf 함수의 문자를 받게 해서 잘 동작한다.

78행 scanf("%s\n" , str); 81행은 scanf("%d\n", &M);

이처럼 다양한 예를 파악해서 getchar을 쓸지말지 결정해야 한다.

728x90

관련글 더보기

댓글 영역