2014-02-11 73 views
0

我找不到爲什麼這個功能不正常運行:C++文件處理讀取功能錯誤

e1是類別的僱員的對象:

class emp 
{ 
    public: 
     int no; 
     char name[30]; 

     void enter() 
     { 
      std::cout<<"\n enter no. and name"; 
      std::cin>>no; 
      gets(name); 
     } 

     void disp() 
     { 
      std::cout<<"\n\tNo.\t\tName\n\t"<<no<<"\t\t"<<name; 
     } 
}; 

程序永遠不會在if子句。

void modify(int a) 
{ 
    f1.open("emp.txt", ios::ate | ios::nocreate); 
    float pos; 
    f1.seekg(0, ios::beg); 
    while (!f1.eof()) 
    { 
     f1.read((char*)&e1, sizeof(e1)); 
     if (e1.no == a) // if e1.no == the number to be modified 
     { 
      pos = f1.tellg(); 
      pos = pos - sizeof(e1) 
      e1.enter(); // enter new e1 details, function declared in class 
      f1.seekp(pos, ios::beg); 
      f1.write((char*)&e1, sizeof(e1)); // overwrite prev rec. 
      cout << "\n modified"; 
     } 
    } 
    f1.close(); 
} 
+0

什麼是'''int a'''? – turnt

+1

不要使用'!eof'作爲循環條件。認真。閱讀過程中,當您觸碰EOF時,您的循環在「讀取」後不會停止。 –

+1

我希望你的Employee類不會從另一個繼承。 –

回答

2

你不能像這樣反序列化一個類。從實例基址指針覆蓋內存很可能會造成嚴重破壞,並將您發送到Undefined Behavior land。如果你希望像這樣閱讀,就需要考慮對象內存佈局(提示:除非你的課程非常簡單,否則它很可能不起作用)。

例如,如果Employee類從另一個類繼承,則該類的第一個成員通常是指向虛擬表的指針。如果你這樣讀,你會覆蓋vtable指針。不好。

有可能像這樣讀取一個C結構體,但只要它包含指針,它就會結束,因爲下次您閱讀時,指向內存可能不是您的。

由於您正在使用C++與可能的成員像字符串,向量等,像這樣的序列化保證會失敗,因爲他們使用動態內存分配。


編輯

既然您發佈EMP的定義,我想我知道發生了什麼。我假定emp.txt是由另一個進程(或手動)寫入的文件。

我已經寫了一小段代碼來說明爲什麼像你這樣,你將有問題的閱讀對象:

emp e; 
std::cout << "sizeof(emp) = " << sizeof(emp) <<std::endl; 
std::cout << "sizeof(emp::no) = " << sizeof(e.no) <<std::endl; 
std::cout << "sizeof(emp::name) = " << sizeof(e.name) <<std::endl; 

std::cout << "&e = " << &e <<std::endl; 
std::cout << "&e.no = " << &e.no <<std::endl; 
std::cout << "&e.name = " << &e.name <<std::endl; 

,這裏是我得到了一個運行輸出:

sizeof(emp) = 36 
sizeof(emp::no) = 4 
sizeof(emp::name) = 30 
&e = 00BBFDF4 
&e.no = 00BBFDF4 
&e.name = 00BBFDF8 

我們可以看到,no是在對象的開始處:好。我們還可以看到name位於內存之後(00BBFDF8 - 00BBFDF4 == sizeof(emp.no))。然而,當我們認爲它應該是34時,對象的大小是36。這是因爲對齊。我的系統默認的一個是4.

我懷疑emp.txt中的數據包含2個額外的字節來處理內存對齊。所以通過閱讀使用sizeof(e1),你讀了2個額外的字節。您正處於下一個整數的中間。這顯然會破壞你在下一次閱讀時期待的數據。

然後還有一個閱讀名稱的問題。即使對齊和內存佈局與您的程序完全相同,您的文本文件也需要根據sizeof(name)編寫,因此每個員工名稱都必須用額外字符(空格?)填充爲固定大小( 30個字節)。我懷疑輸入文件是這樣寫的。

我建議你根據你的輸入文件而不是你用來存儲數據的類來實現讀取邏輯。另外,如果數據不是固定的大小,那麼編輯文件將很困難。

+1

恩,這是我的第一年。 C++ñ我不明白這一切。 class emp是v。simple: class emp { public: int no; char name [30]; void enter() cout <<「\ n輸入號碼和姓名」; cin >> no; gets(name); } void disp() { cout <<「\ n \ tNo。\ t \ tName \ n \ t」<< no <<「\ t \ t」<< name; } }; –

+1

由於您添加了emp的定義,我更新了我的答案和您的問題。 –

+1

非常感謝。問題已經解決了。 –

0

您在fstream::open()的flags參數中缺少ios::binary:確定您在此處執行二進制I/O操作。

然而,其他註釋的所有注意事項仍然是真實的:您應該添加(應該添加,如果這不解決問題)至少定義e1。

+0

感謝您指出錯誤。我忽視了這一點,並引發了許多問題。 –