C 문법중 getline이 돌아가는 것이 이해가 안됩니다.
{
char ch[2];
ifstream fin;
fin.open("C:\\graph.dat", ios_base::in);
if(!fin.is_open()){
cout << "cannot open " << endl;
exit(1);
}
while(!fin.eof()){
fin.getline(ch,3,',');
cout << ch << " ";
}
return 0;
}
파일 내용
10,
1,2,1,3,2,4,3,4,4,5,5,6,5,7,8,9,8,10
-----------------------
여기서
fin.getline(ch,3,',');
이거 실행시에 3을 2로 바꾸면 왜 안되는지 궁금합니다.
그냥 무한루프를 돌더군요. 최대로 입력받을 문자라고 알고 있기는 한데...
프로그래밍을 할때는 2로 했다가 안되길래 3으로 해봤는데 되었습니다.
그 이유를 찾기위해서 노력했지만... 역시나 답이 안나오는군요.
어렴풋이 개행문자 때문일거같다..라고 추측은 하는데 확실한 답을 모르겠습니다.
제궁금증좀 꼭 풀어주십시오! 수고하십시오.
---------------------------------------------------------------------------------------------------
istream& getline(char *str, int count, char delim); |
위와 같은 getline() 함수의 정의에서 두 번째 인자인 count의 의미를 잘 못 해석하신 것 같습니다. count는 읽어들여야 할 문자의 최대 갯수가 아니고 str 문자열의 크기입니다.
우선 문자열은 해당 문자열의 마지막을 나타내는 NULL 문자(C/C++에서 '\0'로 표현)가 끝에 존재해야 합니다.
fin.getline(str, 2, ','); |
위와 같은 경우 getline() 함수에게 2개의 문자를 읽어들이라고 선언한 게 아니라는 겁니다! 결과물이 들어갈 str 문자열의 길이가 2이라고 쓴 것입니다.
그러므로 getline()은 문자 한 개를 읽고 str에 넣습니다. 그리고 str의 크기가 2라고 했으니 끝에 NULL 문자가 들어갈 자리 밖에 안 남은 것이죠. 결국 str 문자열에는 (끝에 보이지 않는 NULL 문자를 포함해서) "1" 밖에 들어가지 않는 것입니다.
결과적으로 보면 두 번째 인자인 count에는 앞으로 읽어들일 데이터의 최고 길이 + 1로 설정하셔야 합니다. 질문자께서 올려주신 예와 같이 "10"이 가장 긴 데이터라면 3으로 설정해야 하는 것이죠.
그럼, 아무튼 이번엔 "1"만 읽고 출력한 후 다음 getline()을 수행하면 되는데 왜 무한 루프가 되는 것일까요? 바로 getline() 함수의 스트림 버퍼를 읽어들이는 방식에 문제가 있습니다.
우선 위에서 말씀 드린 내용을 정리해 보면, getline() 함수는 count - 1 만큼의 문자만 str에 저장합니다. 그러나 더 중요한 것은 getline() 함수는 반드시 count 만큼의 입력 문자들 중에 delim 문자(이 번 경우에는 쉽표)를 찾아야 합니다.
10,... |
입력 파일의 내용이 위와 같으므로 count를 2로 정할 경우 첫 문자인 '1'만 읽고 str에 저장합니다. 그리고 str에 문자열의 끝을 알리는 NULL 문자도 삽입합니다. 그리고 마지막으로 한 문자를 더 읽어보고 쉼표(,)인지 확인합니다. 그러나 두 번째 문자는 쉼표가 아닌 '0'이죠.
찾으려는 구분자 delim을 못 찾았으므로 스트림 내부적으로 setstate() 함수를 사용하여 실패 상황을 알립니다. 그리고 그 이후로 스트림은 파일에서 아무 것도 읽어올 수 없는 상태가 되어버린답니다. 아무 것도 읽어오지 못 하니 당연히 파일의 끝(EOF)에 도달할 수 없고 무한 반복문이 되어버리는 것이죠.
참고로 위에서 얘기한 스트림의 실패 상태는 다음 함수를 사용해서 직접 확인할 수 있습니다.
while (!fin.eof() && !fin.fail()) { fin.getline(str, 2, ','); if (fin.fail()) { cout << "getline() failed!" << endl; } cout << str << endl; } |
그럼 도움이 되셨기를 바랍니다.
'C & C++ 관련' 카테고리의 다른 글
isspace 함수 - 공백문자 지우기 (0) | 2007.05.05 |
---|---|
exit(0), exit(1) (0) | 2007.04.24 |
malloc은 Heap에 변수를 할당하는 함수입니다. (0) | 2007.04.21 |