2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Некорректное завершение программы
Сообщение14.03.2016, 23:49 
Аватара пользователя


26/03/13
326
Russia
пишу программу для записи объектов в файл с перегрузкой операторов >> & <<

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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';
        fstream file;
        file.open("TAB.txt");
        employee one;
        while(ch=='y'){ // цикл для записи
                one.putdata();
                file<<one; // write data into file
                cout<<"Go on?(y,n): ";cin>>ch;
        }
//      file.seekg(0);
        while(!file.eof()){ // цикл для чтения из файла
                file>>one;
                one.getdata();
        }
        file.close();
        system("pause");
        return 0;
}
 


после ввода объектов программа зависает, подскажите пожалуйста в чём дело?

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение15.03.2016, 01:11 
Заслуженный участник


26/05/14
981
1. Закомментированный вызов file.seekg(0) означает, что вы читаете за концом файла. При этом file.eof() не возвращает истину, чтобы он вернул истину надо сделать одно неудачное чтение а его у вас нет.

2. Когда вы что-то написали в файл, и собираетесь это же прочитать, вам надо сбросить буфера:
http://stackoverflow.com/questions/1753 ... me-fstream

3. Я бы так делать не стал. Я бы открыл файл на запись, записал, закрыл, открыл на чтение, прочитал, закрыл. В этом случае нет всех этих скользких мест. RW операции с файлами - сложное место, форматный ввод/вывод тоже. Зря вы собрали их вместе.

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение15.03.2016, 10:49 
Аватара пользователя


26/03/13
326
Russia
Сделал 2 потока: запись и чтение

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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
                file1.flush();
                cout<<"Go on?(y,n): ";cin>>ch;
        }
        file1.close();
        file2.open("TAB.txt");
        while(file2){ // цикл для чтения из файла
                file2>>one;
                one.getdata();
        }
        file2.close();
        system("pause");
        return 0;
}
 


Теперь стало зависать после вывода данных

-- 15.03.2016, 11:04 --

Поставил цикл for и всё норм:

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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){ // цикл для чтения из файла
//              file2>>one;
//              one.getdata();
//      }
        for(int i=0;i<1;i++){
                file2>>one;
                one.getdata();
        }
        file2.close();
        system("pause");
        return 0;
}
 


То есть какая-то ошибка с условием while(file2). В Лафоре написано, что file2 возвращает указатель на объект, который даст true, если нет ошибок и даст 0, если есть ошибка, например конец файла. Можете прокомментировать?

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение15.03.2016, 11:20 
Заслуженный участник


26/05/14
981
Ваш оператор ввода зацикливается при чтении за концом файла. Вам следует проверять конец файла после каждого вызова >>.

Вот здесь есть обсуждение: http://stackoverflow.com/questions/4533 ... s-eof-work

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение16.03.2016, 15:52 
Аватара пользователя


26/03/13
326
Russia
Из данной ссылки я понял, что предлагают выводить посимвольно file2.get(), разве нет способа нормально объекты вывести?

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение16.03.2016, 16:04 
Заслуженный участник


26/05/14
981
Я уточню что имелось ввиду. Если оператор >> не может ввести данные, то переводит поток в "нехорошее" (отсылка к методу good) состояние (в вашем случае eof). Все последующие вызовы >> ничего не делают. Ваш оператор ввода ломается на первом вызове >>. Переменная dummy остаётся не инициализированной. Цикл становится бесконечным.

Чтобы исправить ситуацию, вам нужно проверять "хорошесть" потока в процессе чтения объекта. Об этом написано в первом ответе по ссылке.

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение17.03.2016, 12:19 
Аватара пользователя


26/03/13
326
Russia
Работает:

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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){ // write into a file
        f<<emp.ID<<"-"<<emp.name<<"?";
        return f;
}

istream& operator >> (istream& f,employee& empl){ // read from a file
        char dummy;
        employee tmp;
        if(f>>tmp.ID>>dummy&&dummy=='-'){
                while(f>>dummy&&dummy!='?')
                        tmp.name+=dummy;
                if(f)swap(tmp,empl);
        }
        return f;                              
}
////////////////////////////////////////////////////////////
int main(){
        char ch='y';
        ofstream file1;
        ifstream file2;
        file1.open("TAB.txt");
        employee one;
        while(ch=='y'){ // writing in cycle
                one.putdata();
                file1<<one; // write data into file
                cout<<"Go on?(y,n): "<<endl;cin>>ch;
        }
        file1.close();
        file2.open("TAB.txt");
        while(file2>>one) // reading cycle
                one.getdata();         
        file2.close();
        system("pause");
        return 0;
}

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение17.03.2016, 12:33 
Заслуженный участник


26/05/14
981
Хорошо. Решение корректное. Мне нравится что ваш оператор ввода исполняет подразумеваемый контракт.
Теперь можно полировать, если хотите. Эта функция вводит последовательность символов до разделителя (http://www.cplusplus.com/reference/stri ... g/getline/):
Код:
istream& getline (istream& is, string& str, char delim);
Если вы её задействуете, то вы снизите нагрузку на поток (посимвольное чтение работает медленно), уменьшите фрагментацию памяти (избавитесь от кучи промежуточных строк), уменьшите сложность с квадратичной до линейной (заметно только для длинных строк).

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение17.03.2016, 23:32 
Аватара пользователя


26/03/13
326
Russia
Как-то так:

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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){ // write into a file
        f<<emp.ID<<"-"<<emp.name<<"?";
        return f;
}

istream& operator >> (istream& f,employee& empl){ // read from a file
        char dummy;
        employee tmp;
        if(f>>tmp.ID>>dummy&&dummy=='-'){
                if(getline(f,tmp.name,'?'))             //f>>dummy&&dummy!='?'
                                                                                //tmp.name+=dummy;
                if(f)swap(tmp,empl);
        }
        return f;                              
}
////////////////////////////////////////////////////////////
int main(){
        char ch='y';
        ofstream file1;
        ifstream file2;
        file1.open("TAB.txt");
        employee one;
        while(ch=='y'){ // writing in cycle
                one.putdata();
                file1<<one; // write data into file
                cout<<"Go on?(y,n): "<<endl;cin>>ch;
        }
        file1.close();
        file2.open("TAB.txt");
        while(file2>>one) // reading cycle
                one.getdata();         
        file2.close();
        system("pause");
        return 0;
}

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение17.03.2016, 23:46 
Заслуженный участник


26/05/14
981
Почти идеально. Но есть вариант входного потока, когда оператор ввода не исполняет свой контракт. Хотя в вашей программе это почти не возможно.

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение18.03.2016, 09:09 
Аватара пользователя


26/03/13
326
Russia
Интересно, приведите пример пожалуйста

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение18.03.2016, 09:23 
Заслуженный участник


26/05/14
981
Если оператор >> не может прочитать из потока, он должен перевести поток в "нехорошее" состояние. В вашем случае ввод из потока данных виде "1+" приведёт простому пропуску двух символов и незаполненному объекту, а окружающий код ничего не поймёт, так как поток останется в хорошем состоянии.

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение24.03.2016, 11:14 
Аватара пользователя


26/03/13
326
Russia
Добавил проверку:

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include<iostream>
#include<fstream>
#include<cstring>
#include<cstdlib>
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){ // write into a file
        if(!(f<<emp.ID)){
                cout<<"Wrong ID, try again..."<<endl;
                exit(1);
                }
                else
                        f<<'-';
        return f;
}

istream& operator >> (istream& f,employee& empl){ // read from a file
        char dummy;
        employee tmp;
        if(f>>tmp.ID>>dummy&&dummy=='-'){                                              
                if(getline(f,tmp.name,'?'))             //f>>dummy&&dummy!='?'
                                                                                //tmp.name+=dummy;
                if(f)swap(tmp,empl);
        }
        return f;                              
}
////////////////////////////////////////////////////////////
int main(){
        char ch='y';
        ofstream file1;
        ifstream file2;
        file1.open("TAB.txt");
        employee one;
        while(ch=='y'){ // writing in cycle
                one.putdata();
                file1<<one; // write data into file
                cout<<"Go on?(y,n): "<<endl;cin>>ch;
        }
        file1.close();
        file2.open("TAB.txt");
        while(file2>>one) // reading cycle
                one.getdata();          
        file2.close();
        system("pause");
        return 0;
}

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение24.03.2016, 13:07 
Заслуженный участник


26/05/14
981
Не туда добавили. И реакция на ошибку чрезмерная.

 Профиль  
                  
 
 Re: Некорректное завершение программы
Сообщение27.03.2016, 11:17 
Аватара пользователя


26/03/13
326
Russia
Изменил реакцию на ошибку ввода ID и добавил изменение флага при некорректном выводе из потока

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#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){ // write into a file
        if(!(f<<emp.ID)){
                cout<<"Wrong ID, try again..."<<endl;
                f.clear();
                }
                else
                        f<<'-';
        return f;
}

istream& operator >> (istream& f,employee& empl){ // read from a file
        char dummy;
        employee tmp;
        if(f>>tmp.ID>>dummy&&dummy=='-'){                                              
                if(getline(f,tmp.name,'?'))             //f>>dummy&&dummy!='?'
                                                                                //tmp.name+=dummy;
                if(f)swap(tmp,empl);
        else{
                f.setstate(ios_base::badbit);
                cout<<"Unable to read a file...";
                }              
    }
    return f;                              
}
////////////////////////////////////////////////////////////
int main(){
        char ch='y';
        ofstream file1;
        ifstream file2;
        file1.open("TAB.txt");
        employee one;
        while(ch=='y'){ // writing in cycle
                one.putdata();
                file1<<one; // write data into file
                cout<<"Go on?(y,n): "<<endl;cin>>ch;
        }
        file1.close();
        file2.open("TAB.txt");
        while(file2>>one) // reading cycle
                one.getdata();          
        file2.close();
        system("pause");
        return 0;
}
 

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 16 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group