2012-07-29 30 views
0

如何在文件處理中使用C++字符串?我創建了一個具有C++字符串作爲其私有數據成員之一的類,但是在從文件中讀取時會產生錯誤,即使此時我沒有使用它並在構造函數中使用默認值進行初始化。寫入文件時沒有問題。它工作正常,如果我使用C字符串,而不是我想。有沒有辦法解決這個問題?在文件處理中使用C++字符串

class budget 
{  
    float balance;  
    string due_name,loan_name;    //string objects 
    int year,month;  
    float due_pay,loan_given;  

    public:     
    budget()  
    {  
      balance=0; 
      month=1;   
      due_name="NO BODY";    //default values 
      loan_name="SAFE"; 
      year=0;    
      balance = 0;  
      due_pay=0;   
      loan_given=0;  
    } 
     . 
     . 
     . 
}; 

void read_balance()    //PROBLEM AFTER ENTERING THIS FUNCTION  
{   
    system("cls");   
    budget b;  
    ifstream f1;  
    f1.open("balance.dat",ios::in|ios::binary);  
    while(f1.read((char*)&b,sizeof(b)))  
    { b.show_data();  
    }  
    system("cls");   
    cout<<"No More Records To Display!!";  
    getch();  
    f1.close();  
} 
+7

你能給我們一個你正在談論的樣本嗎? – chris 2012-07-29 19:39:58

+0

那麼,http://whathaveyoutried.com/? – 2012-07-29 19:44:36

+0

什麼是「錯誤」 – 2012-07-29 19:48:50

回答

1

字符串是non-POD data-type。您無法通過讀取/寫入功能從字符串中讀取/寫入字符串。

basic_istream<charT,traits>& read(char_type* s, streamsize n); 

30影響:表現爲未格式化的輸入功能(如在 27.7.2.3,第1段中所述)。在構造一個Sentry對象之後,如果!good()調用可能拋出異常的setstate(failbit),並返回。 否則提取字符並將它們存儲到連續的 陣列的第一個元素由s.323指定的位置 字符被提取並存儲,直到發生以下任一個 : - 存儲了n個字符; - 文件結束髮生在輸入 序列中(在這種情況下,該函數調用可能拋出ios_base :: failure(27.5.5.4))的setstate(failbit | eofbit), 。 31返回:*這。

沒有什麼關於std::string的成員如何放置。看看,或使用boost::serialiationhttp://www.boost.org/doc/libs/1_50_0/libs/serialization/doc/index.html當然你可以寫大小的字符串,然後寫數據,當讀 - 讀大小,分配這個大小的數組,讀取數組中的數據,然後創建字符串。但使用提升更好。

0

在讀取類預算的字符串成員(due_name,loan_name)時,您的代碼逐字節地填充它們。雖然它對於浮動和整數是有意義的,但它不適用於字符串。

字符串被設計爲保持'無限量'的文本,因此它們的構造函數,複製構造函數,連接等必須確保分配實際的內存來存儲文本並在必要時擴展它(並在銷燬時刪除)。從磁盤中以這種方式填充字符串將導致字符串對象內的無效指針(不指向包含文本的實際內存),實際上根本沒有實際讀取文本。

0

解決此問題的最簡單方法是不要在該類中使用C++字符串。計算每個將要存儲的字符串的最大長度,並將字符數組的長度增加一個字節(以允許0終止符)。現在,您可以讀寫該類作爲二進制文件,而無需擔心序列化等。

如果您不想這樣做,則無法在您的類上使用iostream :: read()。您將需要讀取/寫入流的成員函數。這就是序列化是關於...但是你不需要複雜的boost。從本質上講,你會做這樣的事情:

// Read with no error checking :-S 
istream& budget::read(istream& s) 
{ 
    s.read((char*)&balance, sizeof(balance)); 
    s.read((char*)&year, sizeof(year)); 
    s.read((char*)&month, sizeof(month)); 
    s.read((char*)&due_pay, sizeof(due_pay)); 
    s.read((char*)&loan_given, sizeof(loan_given)); 

    size_t length; 
    char *tempstr; 

    // Read due_name 
    s.read((char*)&length, sizeof(length)); 
    tempstr = new char[length]; 
    s.read(tempstr, length); 
    due_name.assign(tempstr, length); 
    delete [] tempstr; 

    // Read loan_name 
    s.read((char*)&length, sizeof(length)); 
    tempstr = new char[length]; 
    s.read(tempstr, length); 
    loan_name.assign(tempstr, length); 
    delete [] tempstr; 

    return s; 
} 

ostream& budget::write(ostream& s) 
{ 
    // etc... 
} 

注意上面,我們已經通過之後,很多字符首先編寫一個大小值,然後序列化的字符串。