2016-03-16 60 views
0

編寫代碼來寫的對象到一個文件,閱讀它們,並在屏幕怪異ifstream的行爲

#include<iostream> 
#include<fstream> 
#include<cstring> 
using namespace std; 
//////////////////////////////////////////////////////////// 
class employee{ 
    private: 
     string name; 
     unsigned long ID; 
    public: 
     employee():name(""),ID(0){} 
     void putdata(){cout<<"Enter employee's name: ";cin>>name;cout<<"Enter employee's ID: ";cin>>ID;} 
     void getdata(){cout<<"Employee's name is: "<<name<<endl;cout<<"Employee's ID is: "<<ID<<endl;} 
     friend ostream& operator << (ostream&,employee&); 
     friend istream& operator >> (istream&,employee&); 
}; 

ostream& operator << (ostream& f,employee& emp){ // запись объекта в файл 
    f<<emp.ID<<"-"<<emp.name<<"?"; 
    return f; 
} 

istream& operator >> (istream& f,employee& empl){ // чтение объекта из файла 
    char dummy; 
    f>>empl.ID>>dummy; 
    f>>dummy; 
    empl.name=""; 
    while(dummy!='?'){ 
     empl.name+=dummy; 
     f>>dummy;  
    } 
} 
//////////////////////////////////////////////////////////// 
int main(){ 
    char ch='y'; 
    ofstream file1; 
    ifstream file2; 
    file1.open("TAB.txt"); 
    employee one; 
    while(ch=='y'){ // цикл для записи 
     one.putdata(); 
     file1<<one; // write data into file 
     cout<<"Go on?(y,n): ";cin>>ch; 
    } 
    file1.close(); 
    file2.open("TAB.txt"); 
    while(file2.good()){ // цикл для чтения из файла 
     file2>>one; 
     one.getdata();  
    } 
    file2.close(); 
    system("pause"); 
    return 0; 
} 

上打印輸入對象後,個節目打印出來掛。我猜while(file2.good())有問題,但我不確定。任何人都能評論?

+0

這意味着'file2'不'good' - 文件的存在嗎?另外嘗試'cout << strerror(errno)'。 – edmz

+0

'file1.open()'創建一個文件 – Andrew

+0

你可能想要'cout <<「繼續?(y,n):」<< std :: endl;'因爲有些實現不允許輸入是終端上輸出的不完整行。 – Logicrat

回答

1

的事情你已經錯過了是EOF沒有設置,直到你讀過去文件結束。最後一次成功讀取將讀取文件末尾(但不是過去),因此EOFfalsegood()true,但流中將沒有更多數據(所以下一次讀取將失敗)。

這就是爲什麼你需要檢查從流中讀取成功。爲了在布爾上下文中使用流對象(while/if test)時幫助解決這個問題,它將自身轉換爲布爾值,該值爲流的狀態。

if (stream) { 
     std::cout << "stream is in good state\n"; 
} 

此外operator>>返回流輸入(因此它可以被鏈接),從而讀出的結果也可以在一個試驗中使用。

if (stream >> value) { 
     std::cout << "The read worked.\n"; 
} 

您的問題是你沒有正確地檢查後的輸入流的狀態。

istream& operator >> (istream& f,employee& empl) 
{ 
    char dummy; 
    f>>empl.ID>>dummy; // Did this work? 
         // You did not test the state of `f` after the read. 
    f>>dummy; 
    empl.name=""; 
    while(dummy!='?'){ 
     empl.name+=dummy; 
     f>>dummy;   // Again if this read fails 
          // because you reached the end of file 
          // then the variable 'dummy' is not updated 
          // then this will go into an infinite loop. 
    } 
} 

每讀都應該檢查流的狀態。

std::istream& operator>>(std::istream& f, employee& empl) 
{ 
    // The other standard thing is that if the read fails. 
    // then you should not alter the state of your object. 
    // so read into a temporary object. 
    char dummy; 


    employee tmp; 
    if (f >> tmp.id >> dummy && dummy == '-') 
    { 
     // We have correctly read the ID (and following '-' char) 
     // Note: The output operator outputs '-' after the ID. 
     // Now we try and read the name. 

     // While the read of the character worked. 
     // and the character is not '?' keep adding it to 
     // name. If we reach then end of the file this 
     // loop will exit. 
     while(f >> dummy && dummy != '?') 
     { 
      tmp.name += dummy; 
     } 

     // If the stream is still good. 
     // then update the object. 
     // If the stream is not good then something went wrong 
     // we reached the end of file before we found the '?' 
     if (f) 
     { 
      using std::swap; 
      swap(tmp, empl); 
     } 
    } 
    return f; 
} 

現在輸入運算符是好的。我們可以正確編寫輸出循環。

while(file2.good()){ 
    file2>>one; 
    one.getdata();  
} 

問題在於file2>>one可能會失敗。你應該測試一下。

while(file2.good()){ 
    if (file2 >> one) { 
     one.getdata();  
    } 
} 

但要做到這一點,正確地把讀作爲條件的時候。如果讀取失敗,則甚至不會進入循環。

while(file2 >> one) 
{ 
    one.getdata();  
} 
-2

您可以添加&& file2.peek()!=EOF到您的主要功能:

while (file2.good() && file2.peek()!=EOF){ 
    file2 >> one; 
    one.getdata(); 
    } 

也許這也是一個好主意,以檢查功能在讀的EOF位:

while (dummy != '?' && !f.eof()){...} 
+2

這裏有一些關於eof()的信息:http://stackoverflow.com/questions/5837639/eof-bad-practice?lq=1 – Tinnuadan

0

最後,它的工作原理(我不敢相信):

#include<iostream> 
#include<fstream> 
#include<cstring> 
using namespace std; 
//////////////////////////////////////////////////////////// 
class employee{ 
    private: 
     string name; 
     unsigned long ID; 
    public: 
     employee():name(""),ID(0){} 
     void putdata(){cout<<"Enter employee's name: ";cin>>name;cout<<"Enter employee's ID: ";cin>>ID;} 
     void getdata(){cout<<"Employee's name is: "<<name<<endl;cout<<"Employee's ID is: "<<ID<<endl;} 
     friend ostream& operator << (ostream&,employee&); 
     friend istream& operator >> (istream&,employee&); 
}; 

ostream& operator << (ostream& f,employee& emp){ // запись объекта в файл 
    f<<emp.ID<<"-"<<emp.name<<"?"; 
    return f; 
} 

istream& operator >> (istream& f,employee& empl){ // чтение объекта из файла 
    char dummy; 
    f>>empl.ID>>dummy; 
    f>>dummy; 
    empl.name=""; 
    while(dummy!='?'){ 
     empl.name+=dummy; 
     f>>dummy;  
    } 
} 
//////////////////////////////////////////////////////////// 
int main(){ 
    char ch='y'; 
    ofstream file1; 
    ifstream file2; 
    file1.open("TAB.txt"); 
    employee one; 
    while(ch=='y'){ // цикл для записи 
     one.putdata(); 
     file1<<one; // write data into file 
     cout<<"Go on?(y,n): ";cin>>ch; 
    } 
    file1.close(); 
    file2.open("TAB.txt"); 
    while(file2.good()&&file2.peek()!=EOF){ // цикл для чтения из файла 

     file2>>one; 
     one.getdata();  
    } 
    file2.close(); 
    system("pause"); 
    return 0; 
} 

我添加file2.peek()!=EOF條件