반응형
int main(void)
{
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
Posted by Real_G