2016-03-16 2 views
0
код

Записи писать объект в файл, читать их и печатать на экранеWeird 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 не установлен, пока вы не прочитаете конец файла. Последнее успешное чтение будет считывать (но не прошло) конец файла, и поэтому EOF - false и good() - true, но данных о потоке больше не будет (поэтому следующее чтение не будет выполнено).

Вот почему вам нужно проверить, что чтение из потока выполнено успешно. Чтобы помочь в этом, когда вы используете объект потока в булевом контексте (while/if test), он преобразует себя в значение boolean, являющееся состоянием потока.

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 состояние