2009-05-06 2 views
0

데이터를 입력하는 텍스트 파일이 있지만 제대로 가져올 수 없습니다. 나는 텍스트 파일을로드하고 데이터를 입력 할 필요가 여기에C++, get 및 >> for ifstream 사용

Michael Davidson  153 Summer Avenue  Evanston  CO 80303 
Ingrid  Johnson  2075 Woodland Road  Aurora   IL 60507 

코드입니다 :

여기 (이 실제 사람들이 걱정하지 마십시오하지 않습니다) 예를 들어 텍스트 파일에서 두 줄입니다 구조체에 넣습니다. 저는 C++을 처음 접했고 (분명히) 저는 get과 >>를 함께 사용하는 데 어려움을 겪고 있습니다. 내가 아래에있는 코드는 "상태"에 도달 할 때까지 제대로 작동합니다. 그런 다음 문제가 발생합니다. 도와 주셔서 감사합니다!

//constants 
const int FIRST_NAME_LEN = 11; 
const int LAST_NAME_LEN = 13; 
const int ADDRESS = 25; 
const int CITY_NAME_LEN = 16; 
const int STATE_LEN = 3; 

//define struct data types 
struct CustomerType { 
    char firstName[FIRST_NAME_LEN]; 
    char lastName[LAST_NAME_LEN]; 
    char streetAddress[ADDRESS]; 
    char city[CITY_NAME_LEN]; 
    char state[STATE_LEN]; 
    int zipCode; 
}; 

//prototype function 
ifstream& getInfo(CustomerType& CT_Struct, ifstream& infile); 

int main() { 

    //declare struct objects 
    CustomerType CT_Struct; 

    ifstream infile("PGM951_customers.txt"); 
    if(!infile) { 
     cerr << "Could not open the input file." << endl; 
     exit(1); //terminates the program 
    } 

//call the function 
getInfo(CT_Struct, infile); 

return 0; 
} 

ifstream& getInfo(CustomerType& CT_Struct, ifstream& infile) { 

    while(infile) { 
     infile.get(CT_Struct.firstName, sizeof(CT_Struct.firstName)); 
     infile.get(CT_Struct.lastName, sizeof(CT_Struct.lastName)); 
     infile.get(CT_Struct.streetAddress, sizeof(CT_Struct.streetAddress)); 
     infile.get(CT_Struct.city, sizeof(CT_Struct.city)); 
     infile.get(CT_Struct.state, sizeof(CT_Struct.state)); 
     infile >> ws; 
     infile >> CT_Struct.zipCode;  

     cout << CT_Struct.firstName << " | " << CT_Struct.lastName << " | " << CT_Struct.streetAddress 
      << " | " << CT_Struct.city << " | " << CT_Struct.state << " | " << CT_Struct.zipCode << endl; 
    } 

return infile; 

} 

=== 8 문자의 상태에서 편집 =========== 독서는 나에게 장난하고 미안 ... 다시 변경하는 것을 잊었다이었다.

+0

"실제 사람들은 걱정하지 않아도됩니다." 이 사람들은 다른 사람을 구걸합니다 : http://en.wikipedia.org/wiki/Michael_Davidson;) –

+0

하지만 그는 실제가 아니기 때문에 그의 의견은 중요하지 않습니다. . ;) – jalf

+0

"무엇이 잘못되었는지"를 말하지 마십시오! 상태가 있지만 지퍼가 고장 나거나 상태가 잘못 되었나요? – crashmstr

답변

0

내가 너라면 처음부터 다시 시작하겠다. 나는 것 : 데이터 대신 문자 배열의

  • 사용 표준 : : 문자열은
  • 는 이제 stringstream
  • 를 사용하여 라인을 구문 분석 표준 :의 getline
  • 을 사용하여 파일에서 한 번에 라인을 읽고 포맷 및 포맷되지 않은 입력을 혼합하지 않도록하는 것은
+0

이것은 까다로운 이유는 이름이 때로는 3, 4 또는 심지어 5 "단어"라는 것입니다. 거리 이름과 도시도 비슷하게 가변적입니다. – dicroce

+0

질문자가 입력 데이터를 제어하는 ​​학습 연습이라고 가정했습니다. 그렇지 않은 경우 XML 또는 CSV와 같은 형식을 입력으로 조사해야합니다. –

+0

고정 크기 필드 형식을 사용하는 것이 가장 쉬운 방법입니다. 필드 구분 문자를 사용하는 경우 필드 내에서 필드 구분 기호를 이스케이프 처리하거나 크기를 인코딩 형식으로 인코딩하거나 XML과 같이 무거운 가중치 형식으로 정의해야합니다. –

0

이 내 접근 방식은 다음과 같다 : 각 라인 읽기)

1 전 n 끝난 버퍼. 2) 작성해야 할 split() 함수를 사용하십시오. 이 함수는 문자열을 입력으로 받아서 목록을 반환해야합니다. 또한 구분 기호가 필요합니다. 이 경우 구분 기호는 ''입니다. 3) 목록을 신중히 반복하십시오 (중간 이름이 없습니까?) 1 단어 또는 3 단어 거리 이름은 어떨까요? 이 열의 대부분은 단어의 수에 따라 실제로 가변적이며 whitspace 이외의 분리자를 갖지 않으므로 이것은 상당히 어려운 작업입니다. 중간 이름을 가진 사람이 없다면 처음 두 개의 열이 성과 이름이라고 생각할 수 있습니다. 마지막 두 가지는 무엇인지 확실히 알 수 있습니다. 그들 사이의 모든 것은 단일 주소 필드에 할당 될 수 있습니다.

3

streetAddress에 공백이있는 istream::get() 나누기가 문제입니다.

한 가지 방법은 토큰의 수에 따라 다음 stringsvector하고, 말에 먼저 입력 라인을 토큰 화하는 것입니다 귀하의 CustomerType의 해당 필드에 이러한 변환 :

vector<string> tokenize(string& line, char delim=' ') { 
     vector<string> tokens; 
     size_t spos = 0, epos = string::npos; 
     while ((epos = line.find_first_of(delim)) != string::npos) { 
      tokens.push_back(line.substr(spos, epos - spos)); 
      spos = epos; 
     } 
     return tokens;  
} 

내가 스트림 차라리 CustomerType에 대한 추출 연산자 :

struct CustomerType { 
    friend istream& operator>>(istream& i, CustomerType& c); 
    string firstName, lastName, ...; 
    // ... 
}; 

istream& operator>>(istream& i, CustomerType& c) {  
    i >> c.firstName >> c.lastName; 
    string s1, s2, s3; 
    i >> s1 >> s2 >> s3; 
    c.streetAddress = s1 + s2 + s3; 
    i >> c.city >> c.state >> c.zipCode; 
    return i; 
} 
+0

나는 그것이 일반적으로 더 약하다는 것에 동의하지만, 연산자가 과부하 인 가난한 사람에게 선물을주고 싶습니까? :-) –

+0

이것이 내가 제안한 것입니다. 내가 생각할 수있는 유일한 문제는 주소 필드에 여러 항목의 항목이있을 수 있지만, 그렇다면 다른 문자가 필드 (탭 또는 | 내 아이디어가 될 수 있음)를 분할하는 데 필요할 것이고 그 다음에는 다른 분리 기호를 사용하여 get()을 호출하십시오. – workmad3

+0

>> >> 연산자가 항상 ws에서 중단되는 반면, count, end of line 또는 구분 기호 (지정되지 않음)까지 얻을 수 있으니 공백으로 중단되지 않을 것이라고 생각했습니다. – crashmstr

1

당신은 당신의 우편 번호를 포함하고 당신의 분야보다 큰 주, 8 개 문자를 받고있어.

infile >> skipws >> CT_Struct.firstName 
     >> CT_Struct.lastName 
     >> ... ; 

(업데이트 : 또한 skipws 연산자를 사용하도록 유혹 할 것

. 그게 내가 메모리에서이 올바른 근사 더 밀접이라고하고 무엇을 얻을.)