ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 버퍼(buffer) c/c++
    헷갈렸던것 2021. 9. 7. 03:34
    728x90

    C언어


    char a, b;
    scanf("%c", &a);
    scanf("%c", &b);
    
    printf("국어 성적은%c\n", a);
    printf("과학 성적은%c", b);

    위의 코드를 살펴봅시다. 

    char형 a와 b를 입력받아 그대로 출력해주는 코드입니다.

    char a 에 b를 입력하고 char b 에 f를 입력해보겠습니다.

    하지만 실행 시켜보면

    b를 누르고 엔터키만 눌렀는데 갑자기 다 출력 되고 프로그램이 멈췄습니다.

    아직 char b를 입력도 안받았는데 프로그램이 멈췄습니다. 이유가 뭘까요?

    바로 '버퍼'입니다.

    우리는 여러 입력을 받을 때, 스트림을 사용하여 키보드와 프로그램을 연결시킵니다.

    버퍼는 바로 키보드와 프로그램 사이에서 입력한 value를 더욱 효율적으로 연결하기 위해 존재합니다.

    따라서 키보드로 입력한 값이 바로 char a로 가는게 아니라 입력받을 수 있는 버퍼에 모두 모아서 한번에 

    char a ,char b로 값을 할당해 줍니다.

    우리는 지금 char형 즉, 문자를 입력 받습니다.

    방금 우리는 char a를 입력하기 위해 b를 누르고 엔터를 눌렀습니다. 우리는 char형을 받고 있으므로 

    개행문자 '\n'까지 모두 받게 되는 것입니다.

    따라서 먼저 입력한 b는 char a 로 할당되고 버퍼에 남은 문자는 '\n'이므로 '\n'이 char b로 할당되어집니다.

    그래서 우리가 scanf("%d" , &b)가 누락된것 처럼 보인것입니다. 이미 앞에 우리는 b와 엔터키(\n) 두번을 눌렀으므로

    두개를 각각 할당한 것입니다.

    그러면 아예 문자를 안넣고 char a에 엔터 , char b에 엔터 를 입력하면 어떻게 될까요?

    즉, 그냥 엔터,엔터만 누르면

    왼쪽 사진처럼 되는것을 알 수 있습니다. 오른쪽 사진은 이해를 쉽게 흰색 펜으로 개행문자가 들어간것을 표시해주었습니다.

    그렇다면 char을 받는 것은 \n문자까지 받았는데 만약 문자형이 아니라 정수형(int)로 받으면 어떻게 될까요?

    int a, b;
    scanf("%d", &a);
    scanf("%d", &b);
    
    printf("국어 성적은%d\n", a);
    printf("과학 성적은%d", b);

    똑같이 int a 에 엔터, int b에 엔터를 입력해보면

    입력커서가 무한히 내려갑니다.

    즉, 개행문자(\n)를 받지 않는 다는 것입니다.

     

     

    그럼 숫자를 넣어보겠습니다. int a에 100을 넣고 int b에 50을 넣게 되면 

    우리는 100, 엔터(\n), 50, 엔터(\n) 를 입력하게 됩니다.

     잘 입력되는 것을 알 수 있습니다. 

    즉, 정수형(int)은 개행문자를 무시하므로 버퍼에 \n가 있는것을 신경안써줘도 됩니다.

     

     

    그럼 char형을 연속으로 받을때, 어떻게 하면 받을 수 있을까? 하면 보통 getchar() 함수를 씁니다.

     char a, b;
    scanf("%c", &a);
    getchar();
    scanf("%c", &b);
    
    printf("국어 성적은%c\n", a);
    printf("과학 성적은%c", b);

    scanf 사이에 getchar()함수가 들어간것을 알 수 있습니다. 

    getchar함수는 말그대로 char형을 받는 다는 것입니다.

    아까 char a를 받을려고 'b'와 엔터(\n)키를 눌렀습니다. 그러면 먼저 눌러진 b는 char a에 할당되고

    버퍼에 남겨진 엔터(\n)는 getchar()함수에 의해 받아지게 됩니다.

    그러면 버퍼에 남겨진 문자는 아무것도 없으므로 정상적으로 char b를 받을 수 있게 됩니다.

    잘 받아지는 것을 알 수 있습니다.

     

     

     

    결론적으로 c언어에서 char형 변수를 받을 때는 버퍼떄문에 항상 주의를 해주어야 합니다.

    c언어에서 char[] 문자열을 %s로 입력 받는데 이때는 \n문자를 무시하는 것 같습니다.


    c++

    char a,b,c;
    cin >> a;
    cin >> b;
    cin >> c;
    cout << a <<' ' << b <<' '<< c;

    c++에서는 입력함수로 보통 cin함수를 많이 사용합니다. c에서의 scanf와 달리 cin함수는 \n 전까지의 입력을 

    결과값으로 받아들입니다. 

    따라서 위의 코드에서 char a에 x를 입력, char b에 y를 입력 char c에 z를 입력하면

    버퍼에는 x, \n, y, \n, z, \n이 존재하게 됩니다. 

    프로그램을 실행하면

    정확히 잘 실행하는 것을 볼 수 있습니다. 

    번외로 a,b,c를 char형이 아닌 string 형으로 바꾸어도 정상적으로 실행됩니다.

    cin함수는 \n을 무시하기 떄문입니다. 대신 버퍼에는 \n를 남겨둡니다.

     

    하지만 문자열을 받을때, cin함수는 공백을 받을 수 없습니다. 

    예를 들어 "I have a car" 같은 문장은 공백이 들어가는 문자입니다. 즉, cin함수로 받을 수 없는 것입니다.

    getline(cin,string) 함수는 string 형태를 cin능력으로 공백까지 다 받겠습니다 라는 의미입니다.

    즉 getline 함수는 입력받는 줄에 모든것을 입력 받을 수 있게 됩니다.

    오직 string 형인 변수에만 사용가능합니다!

    int n;
    cin >> n;
    string st;
    getline(cin,st);
    cout << n <<' '<<st;

    int n에 5를 입력하고 string st에 "I have a car"를 입력해 보겠습니다.

    그러면 버퍼에는 5, \n, I have a car, \n이 들어오게 됩니다.

    하지만 5를 입력하자 마자 5를 출력하고 프로그램이 종료 되었습니다.

    앞에서 말했듯이 getline함수는 입력받는 줄에 모든 문자를 입력받습니다. 공백을 포함해서요.

    처음에 int n에 5를 누르고 엔터(\n)를 누릅니다. 그러면 5는 int n에 할당되어지고 버퍼에는 \n이 남습니다.

    이때, 버퍼에 남겨진 \n을 getline함수가 받아버리는 겁니다. 

    떄문에 string st는 \n만 할당받은채 cout함수에서 n만 출력 되고 끝이 나는 겁니다.

    이를 방지 하기 위하여 c언어에서는 getchar()함수를 쓰듯이 c++에서는 cin.ignore()함수를 사용합니다.

    말그대로 버퍼에 있는 모든것들을 무시한다는 의미입니다. 

    아까같이 버퍼에 \n이 있어도 무시하겠다는 의미입니다.

    int n;
    cin >> n;
    cin.ignore();
    string st;
    getline(cin,st);
    cout <<n <<' '<<st;

    cin >> n; 과 getline(cin,st); 사이에 cin.ignore(); 함수를 쓰면 됩니다.

    정상적으로 작동하는 것을 알 수 있습니다.

     

     

    버퍼가 발생하는 이유를 지금까지 대충 이해하고 넘어갔었는데 이번 기회에 조금 더 자세히 배우게 되어 다행이라고

    생각합니다.

    모르는것을 대충 넘어가는 것보다 시간이 늦어지더라도 하나의 개념을 정확히 알고 넘어가는게 중요한것 같습니다.

    컴퓨터는 대충대충하면 안되기 때문입니다.

    '헷갈렸던것' 카테고리의 다른 글

    비트 연산  (0) 2022.01.21
    삼항조건연산자  (0) 2021.09.27
    실수형 (부동 소수점)  (0) 2021.09.03
Designed by Tistory.