c++의 STL을 쓰다 보면, 의도치 않게 공백을 포함해서 입력을 받아야 하는 경우가 있습니다. 이 때, 저는 fgets를 많이 이용합니다. 이 함수의 원형은 아래와 같습니다.

 

 2번째 인자인 num이 눈에 보이는데요. num - 1개의 문자만큼 받거나, '\n'을 입력받거나, 아니면 EOF가 입력될 때 까지 입력을 받습니다. gets와는 다른 특성을 가지는데요.

 

 num이 없어요. 몇 byte까지 받아야 되는 정보가 없고, 단지 포인터만 넘겨줍니다. 문자열의 시작 주소만 넘겨준 상태에서, 크기를 모르는 상태에서 무한정 받아버리면 어떻게 될까요?

 

 

 허용되지 않는 공간에 이상한 값을 덮어씌워 버릴 수 있어요. 안전하지 않아요. bound 조차 없기 때문입니다. 얼만큼 받을 건지에 대해서 넘겨주기 때문에, 기본적인 bound 처리를 한다는 이야기입니다.

 

 


 gets 함수는 성공적으로 입력을 받으면, str을 리턴합니다. 그렇지 않으면, NULL을 리턴합니다.

 

 

 이 경우, 크게 2가지가 있을 수 있어요. eof를 만났는지. 아니면, error가 발생했는지.

 

 

 2가지에 대해서 어떻게 구분하는지는, 추후에 다시 언급을 하도록 하겠습니다. 여기에서는 그냥 feof랑, ferror만 있다고만 아시면 됩니다. 예제 프로그램을 봅시다.

 

 


 1번 프로그램입니다.

 

 

 사실 별 게 없어보입니다. 더 정확하게 말하면, stdin, 즉 표준 입출력으로부터 계속 입력을 받고, 그 내용을 출력해 주는 프로그램임을 알 수 있어요. 테스트 데이터는 아래와 같습니다.

 

 프로그램이 어떻게 출력되는지 보겠습니다.

 

 

 뭔가 꽤 복잡해 보이는데요. 처음 str은 a부터 출력되었습니다. 그리고 2번째 str은 b가 출력되고 cd 패턴이 이어지고 있습니다. 일단 이 부분만 보도록 하겠습니다. ab패턴은 50번 이어졌습니다. 그런데, 2번째에 b가 나왔다는 이야기는 50번째에는 a만 들어갔다는 이야기입니다.

 

 

 이는, 입력 받는 길이에, 널 문자를 더한 값인 100만큼 받으라고 했기 때문입니다. 그러면, 다음에 입력받을 때, b부터 들어갈 겁니다. 그 다음에 cd를 49번 입력을 받을 겁니다.

 

 

 그 다음에는, cd와 '\n'이 있습니다. 이 함수는 개행도 같이 들어오는데요.

 

 

 이 때, 개행을 제거하기 위해서, str[strlen(str)-1] = 0을 넣는 트릭을 씁니다. 당연하게도, 이 트릭을 썼는데 맞았는데 왜 틀리나요? 질문이 올라왔는데요. 개행까지 입력을 받은 경우에만 그렇게 들어옵니다. 그렇지 않은 경우도 항상 염두에 두고 있어야 합니다. 개행이 들어온 경우에만 그것을 제거하는 올바른 코드는 아래와 같습니다.

 

 

 즉, fgets로 입력을 받았을 때, 문자열의 끝에는 항상 개행문자가 온다는 가정을 하면 안 됩니다. 그러면 실험을 하나 더 해 봅시다. ab패턴 49개와 a가 concat 되어 있는 길이 99짜리 문자열을 받고, 다음 줄에는 ef패턴 55개짜리 문자열을 받는다고 합시다.

 

 이 때에는 어떻게 동작할까요? ab..a 다음에 '\n'도 fgets가 받는 문자열이라고 생각하면 쉽게 생각하실 수 있습니다.

 

 

 먼저 a까지 입력을 받습니다. 99개를 입력받은 셈입니다. 다음에 개행 문자가 들어옵니다.

 

 

 그러면 개행 문자만 받고, 다음 문자열을 받으러 갈 겁니다.

 

 

 실제로 출력되는 결과는 위와 같습니다.