2009-05-06 40 views
0

我有一個文本文件,我從中輸入數據,但我似乎無法得到它的權利。C++,使用獲取和>>爲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;) – 2009-05-06 19:59:19

+0

但他的意見並不重要,因爲他不是真的。 ;) – jalf 2009-05-06 20:00:50

+0

你不要告訴我們「出了什麼問題」!狀態是否存在,但是zip文件崩潰了,或者狀態是錯誤的? – crashmstr 2009-05-06 20:13:36

回答

0

如果我是你,我會從頭開始。我想:

  • 使用std ::字符串代替字符數組爲您的數據
  • 使用std ::函數getline
  • 解析排隊使用字符串流
  • 在從文件中讀取的時間線避免混合格式和無格式輸入
+0

這很棘手的原因是,名稱有時會有3,4或甚至5個「單詞」。街道名稱和城市都是類似的變量。 – dicroce 2009-05-06 20:05:46

+0

我認爲這是一個學習練習,提問者控制輸入數據。如果不是,他顯然應該調查格式,如XML或CSV輸入。 – 2009-05-06 20:09:08

+0

使用固定大小的字段格式是最簡單的方法。如果使用字段分隔符字符,則需要擔心在字段內轉義字段分隔符,或者將大小編碼爲格式,或者使用像XML這樣的重量級定義格式。 – 2009-05-06 21:21:35

0

我的這種方法將是以下:

1)讀取的每一行我nto空終止的緩衝區。 2)使用你必須寫的split()函數。這個函數應該把一個字符串作爲輸入並返回一個列表。它也應該採取分隔符。在這種情況下分隔符是''。 3)仔細地遍歷列表(是否沒有中間名?)關於1個字或3個字的街道名稱?由於許多這些列的字數實際上是可變的,並且除了whitspace之外沒有分隔符,這可能證明是一項相當艱鉅的任務。如果你從來沒有中間名,你可以假設前兩列是名和姓。你肯定知道最後兩個是什麼。它們之間的所有內容都可以分配給一個地址字段。

3

問題是istream::get()中斷streetAddress其中有空格。

一種方法是先標記化輸入線成說,中strings一個vector然後根據不同的令牌數量轉換這些你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

我同意這通常是比較費時的,但是我們是否想要向可憐的傢伙介紹操作員過度使用權? :-) – 2009-05-06 20:10:42

+0

這是我的建議。只有我能想到的問題是地址字段中可能有不定數量的項目,但如果是這樣的話,則需要不同的字符來分割字段(選項卡或|將是我的想法),然後您可以使用get()用不同的分隔符:) – workmad3 2009-05-06 20:10:58

+0

我一直在想直到count,行尾或分隔符(沒有指定)爲止,所以它不會在空白處中斷,而>>操作符總是在ws上斷開。 – crashmstr 2009-05-06 20:11:54

1

你得到8個字符的國家,其中包括所有的郵政編碼,並且比你的領域更大。

這也將會是很有誘惑力的使用skipws操作:

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

(更新:這就是我得到這樣做,從內存這是更緊密地接近正確。)

相關問題