[c++] iterator로 나타내는 구조체의 멤버변수에 값을 어떻게 ?
#include <fstream> #include <algorithm> #include <vector> #include <cctype> #include <iterator> #include "sum_c++.h" using namespace std; int main() { char str[100]; string temp; vector<student_info> students; typedef string::iterator iter; typedef vector<student_info>::iterator v_iter; bool choice; ifstream read_file("info.txt"); while(!read_file.eof()) //read_file.good() { choice = false; read_file.getline(str,100,'\n'); temp = str; iter i = temp.begin(); v_iter count = students.begin(); while( i != temp.end() ) { while( i != temp.end() && isspace(*i) ) ++i; iter j = i; while( j != temp.end() && !isspace(*j) ) ++j; if( i != j && choice == false) { 1번쨰...... students[count].name = string(i,j); 2번째...... temp = string(i,j); temp.copy((*count).name, 30); 3번째...... (*count).name = string(i,j); i = j; choice = true; } else if( i != j && choice == true ) // students[count].grade = string(i,j); temp = string(i,j); //cout << "count++ " << count+1 << endl; ++count; } } }
c++ 초보입니다.
위의 프로그램은 파일에서 한 라인씩 값을 읽어와 공백을 기준으로 한 단어씩 나눠 구조체에 저장하는 프로그램입니다.
구조체 형식
struct student_info { std::string name; double grade; }
네가지 질문이 있습니다.
1. 구조체 배열와 스트링에 대해 index를 쓰지않고 iterator를 사용합니다.
"cout << iterator변수" 로 그 값을 출력하려고 하면 에러가납니다.
왜 그런가요?
2. 공백을 기준으로 뽑아낸 단어를 구조체의 멤버변수 name에 저장하는 방법을 모르겠습니다.
위의 프로그램에서 세가지 방법으로 각각 해보았는데.. 실행이 되자 않고 세그먼트폴트가 됩니다.
3. 파일의 끝에 대한 질문입니다.
이 프로그램을 c로 구현한적이 있는데..
그때도 파일의 끝 문제때문에 고심했었습니다.
c에서 while( read() == EOF ) 대략 이런식으로 구현을 했는데..
EOF를 인식하지 못해서 무한루프를 돌았었습니다.
그래서 ftell을 이용해 파일의 끝위치를 알아내서 그것을 이용해서 비교를 하였습니다.
이번에 c++ 구현시에도 eof() 함수가 있어서 이것을 이용해서 검사를 하는데.. 역시나 파일의 끝을 인식하지 못합니다.
그래서 계속 값을 읽어들이려는 시도를 하는데..
어떻게 해결을 해야하나요?
제가 eof()에 대한 개념을 잘 알지 못하는 것인가요?
4. c++에선 std::string이란 타입이 있습니다.
이것과 캐릭터배열( char a[100]; )과의 차이점을 모르겠습니다.
이 두개가 혼용되어서 사용되는데..
언제 이 둘중 어떤 타입을 사용해야 하는지 잘 구분이 안갑니다.
char str[100]; string temp; .............. read_file.getline(str,100,'\n'); temp = str;
위의 프로그램에서 getline함수는 std::string의 변수를 인수로 받으면 에러가 나더군요..
[ 원래코드.... read_file.getline(temp,100,'\n'); ]
그래서 위와같은 처리를 해주었습니다.
저는 std::string 타입에서 제공하는 멤버함수를 사용하고 싶었거든요..
c는 c 답게..
c++는 c++ 답게 구현하려고 노력중입니다.
그런데..너무 혼란스럽네요^^;;
1. cout << (*iter) 같이 해야 하지 않을지?
1. cout << (*iter) 같이 해야 하지 않을지?
2. 어떤것이 문제인지 코드를 테스트해본 것은 아닙니다만... string 은 그냥 assign하면 되기 때문에 다른 쪽에 문제가 있을 것으로 생각됩니다.
공백을 기준으로 단어들을 쉽게 나누는 방법은 다음과 같이 하시면 더 편할 것입니다.
제가 아는 간단한 방법입니다. file에서 읽은 데이터를 string으로 만들고 위와 같이 stringstream을 사용하면 편합니다. :)
3. while (!ifstream.readline(...).eof()) { ... } 로 해보심이...
4. std::string은 char[] 를 기반으로 안전하고 편리한 method들을 구현해주는 class라고 생각하시면 됩니다. overflow나 underflow처리가 편하고, copy나 substring, finding... 등등, string에 대해서 생각할 수 있는 것들을 모아놓은 것이죠. 원래는 basic_string<>이 있고, string은 basic_string<char> 입니다.
때문에 대부분의 상황에서는 std::string을 쓰는 것이 코드도 깔끔해지고 버그가 생길 확률도 극히 줄어듭니다. char[]를 바로 다루는 것보다 성능이 떨어질 걱정은 보통 안합니다. 많은 경우 char[]를 유저가 처리하는 것보다 오히려 더 빠르기도 하구요.
따라서 C++로 개발하실 때는 std::string을 최대한 활용하도록 하시고, 부득이하게 char 를 사용해야 할 경우만 std::string.c_str() method를 사용하여 char[] 타입으로 바꾸고 사용하시는 것이 좋다고 생각합니다.
ifstream에서 std::string으로 바로 getline()하는 것도 있습니다. 잘 찾아보세요.
Re: [c++] iterator로 나타내는 구조체의 멤버변수에 값을 어떻
count라는 이름 때문에 인덱스로 착각하셨군요. 이것은 인덱스가 아니라 iterator입니다.
코드를 보면 students라는 빈 vector를 만들고 count가 students.begin()을
가리키게 했는데, 지금 상태로는 count가 널 포인터와 비슷하다고 보시면 됩니다.
그런데 *count로 역참조를 했으니 에러가 납니다. 이런 식으로 해보세요.
사실 temp도 필요가 없어보이는군요. 바로 str을 쓰면 되겠습니다.
eof()는 사실 거의 쓸 일이 없는 함수입니다. 이 함수는 파일 포인터가 파일 끝에
위치하는지 알려주는 함수가 아닙니다. 입력에 실패한 이유가 파일 끝 때문인지
알려주는 것이죠. (입력 실패의 원인이 꼭 파일 끝 때문만은 아니므로.) 즉 입력이
적어도 한 번은 실패를 해야 eof()가 true를 반환한다는 뜻입니다. 그리고 대부분의
경우 입력이 성공했는지 실패했는지 여부가 중요하지 실패의 원인이 파일 끝 때문인지는
알 필요도 없지요. 보통은 이런 식으로 합니다.
istream::getline() 함수의 원형을 보시면 에러가 나는 이유를 알 것입니다.
string을 입력할 때는 이 함수가 아니라 다른 함수를 씁니다.
댓글 달기