강의실/정보영재

C언어로 문자열 입력을 받을때 일반적으로 다음의 명령을 사용하게 됩니다.

char str[101];

scanf("%s",str);

이렇게 scanf 로 입력을 받게 되면 "Hello World" 와 같이 스페이스가 있는 문자열은 "Hello" 만을 입력 받게 됩니다.

따라서 scanf 입력시에는 문자열 중에서 단어별로 입력을 받을때 자주 사용하게 됩니다.

하지만 알고리즘상 스페이스를 같이 입력 받아야 할때가 있습니다. 위와 같이 "Hello World" 를 입력 받아서 2개의 단어로 처리 해야 하는지 또는 단어를 분리해야 하는 경우등이 있을수 있는데...

이때는 일반적으로 gets(str) 과 같이 gets 함수를 사용하게 됩니다.

그런데 이 gets() 함수가 치명적인 결함을 가지고 있는데 어떤 문제인가 하면

위와 같이 gets(str) 을 사용했는데 str이 101바이트만 메모리 할당이 되어 있는데 1000바이트의 데이터가 입력이 들어 오는 경우입니다.

일반적으로 char str[101]; 선언을 하면 OS 에서는 현재 사용하고 있지 않은 메모리 중에서 101 바이트를 할당하게 됩니다. 그리고 다른 int a; 와 같이 다른 변수를 선언 하게 되었을때 그 뒤의 메모리를 a 에 할당 할 수 있겠네요.

혹은 다른 프로그램에서 그 뒤의영역을 할당 받아 사용할 수도 있을것입니다.

이렇게 그 뒤의 메모리 영역을 할당받아 사용중에...

gets(str) 에 따라 그 뒤의 메모리 영역에 현재 값이 들어가면 치명적인 오류가 발생할 소지가 있습니다.

그래서 C++11 버젼 부터는 gets() 함수를 지원하지 않게 됩니다.

따라서 C++11 버젼 이후 부터를 떠나서 안전성을 위해서라도 fgets() 함수를 사용하시기를 권장합니다.

fgets() 함수의 사용법은 다음과 같습니다.

fgets(str,101,stdin); //str 은 char str[101], 101 은 최대 크기 101 바이트 이상은 안 읽겠다, stdin 표준입력 에서 읽겠다

fgets 함수는 파일을 버퍼에 읽을때 사용하는 함수인데 표준입력을 파일 형태로 받아 들이면 gets() 와 동일하게 사용할 수 있습니다.

이렇게 읽은 버퍼의 마지막에 '\n'(엔터값) 이 포함 되어 있을 수 있습니다.

이 엔터값을 없애 주기 위해서는 다음과 같은 작업을 수행해 주어야 합니다.

len = strlen(str);

if(str[len-1] == '\n') str[--len] = '\0'; //마지막 글자가 \n(엔터) 라면 \0(NULL) 값으로 바꾸어 준다.

이렇게 처리해서 사용해 주시면 안정성 면에서나 나중에 C++11 이후 버젼에서 갑자기 gets() 함수가 지원이 안될때라도 문제 없이 해결 할 수 있겠네요.

 

 

8 0
  • 공수래공수거 2019.04.15 09:46 신고    

    알고리즘 대회 문제 풀때 참고하면 좋겠습니다.^^

  • 로즈마리 2019.04.15 16:41    

    오호~ 내공있는 팁 감사합니다.

  • 휴식같은 친구 2019.04.15 17:46 신고    

    C언어와 C++언어 문법이 약간 다른가보군요.
    잘 보고 갑니다.
    즐거운 저녁시간 되세요~^^

  • 행복사냥이 2019.04.15 20:57 신고    

    어려워요.ㅠㅠ 열심히 해야할 것 같아요.ㅎ

  • 핑구야 날자 2019.04.16 06:46    

    경우에 따라서는 어떤 명령어를 사용하느냐가 참 중요한 거 같아요

  • 청결원 2019.04.16 06:48 신고    

    포스팅 잘 보고 가네요
    오늘도 즐거운 하루 보내세요~

  • 유하v 2019.04.16 21:07 신고    

    알고리즘은 넘나 어려워요ㅜㅜㅋ

  • 버블프라이스 2019.04.17 04:42 신고    

    어렵지만, 학생분들이 알고리즘 문제를 풀때 참고하면 좋을것 같습니다^^