#include <iostream> #include <fstream> #include <windows.h> using namespace std; struct worker { int codePid, codeCeh, tabNum, yearBirth, codeNation, famStage, workStage, workStageNep, profCode, roz; double ok; char surname[30]; }; int main() { SetConsoleCP(1251); SetConsoleOutputCP(1251); worker w; bool exit; ofstream fout("database.txt", ios_base::out | ios_base::trunc | ios_base::binary); if(!fout.is_open()) { cout<<"Файл не відкритий\n"; return 1; } while(exit) { /* cout<<"Код підпpиємства "; cin>>w.codePid; cout<<"Код цеху "; cin>>w.codeCeh; cout<<"Табельний номеp пpацівника "; cin>>w.tabNum; cout<<"Пpізвище пpацівника "; cin>>w.surname; */ cout<<"Рік наpодження "; cin>>w.yearBirth; /* cout<<"Код національності "; cin>>w.codeNation; cout<<"Сімейний стаж "; cin>>w.famStage; cout<<"Стаж pоботи загальний "; cin>>w.workStage; cout<<"Стаж pоботи непеpеpвний "; cin>>w.workStageNep; cout<<"Код пpофесії "; cin>>w.profCode; cout<<"Розpяд "; cin>>w.roz; cout<<"Оклад "; cin>>w.ok; */ fout.write((char*)&w, sizeof(w)); cout<<"0 - закінчити, 1 - продовжити\n"; cin>>exit; } fout.close(); int d20=0, v20d30=0, b30=0; ifstream fin("database.txt", ios_base::in | ios_base::binary); if(!fin.is_open()) { cout<<"Файл не відкритий\n"; return 1; } while(!fin.eof()) { fin.read((char*)&w, sizeof(w)); cout<<w.yearBirth<<" "; if(2016-w.yearBirth<20) d20++; else if(2016-w.yearBirth>20 && 2016-w.yearBirth<30) v20d30++; else if(2016-w.yearBirth>30) b30++; } cout<<endl<<d20<<" "<<v20d30<<" "<<b30; return 0; } 

screen The screenshot shows that 5 was read by the program 2 times. Why did it happen?

  • Classic. The eof flag is set after unsuccessful reading. Therefore, we first read and then trust. You have the opposite. - pavel
  • How then to rewrite this segment? Using do while got the same result - Maxim Kalani
  • @VladD With duplicates a strange situation, if you think about it :) On the one hand, the problem is clearly the same, on the other - each one asks the question in his own way. To ask the question, as in the link you specified, you need to know if not the whole answer, then half ... - Harry
  • @Harry: Well, it’s like a canonical question in order to make others duplicate to it. - VladD

1 answer 1

You have incorrectly compiled a cycle of reading from the file.

 while(!fin.eof()) { fin.read((char*)&w, sizeof(w)); cout<<w.yearBirth<<" "; if(2016-w.yearBirth<20) d20++; else if(2016-w.yearBirth>20 && 2016-w.yearBirth<30) v20d30++; else if(2016-w.yearBirth>30) b30++; } 

The eof status eof not occur immediately after you have read the last entry. It comes after you try to read a non-existing record after the last record of the file.

Therefore, when the last entry has already been read, you will nevertheless get back inside the loop, since the loop condition will be true.

On this offer

  fin.read((char*)&w, sizeof(w)); 

the situation with eof will happen, but you still try to output data from the object w , which remained in it after the previous reading of the last record of the file.

  cout<<w.yearBirth<<" "; if(2016-w.yearBirth<20) d20++; else if(2016-w.yearBirth>20 && 2016-w.yearBirth<30) v20d30++; else if(2016-w.yearBirth>30) b30++; 

It will be correct to organize a cycle, for example, as follows

 while(fin.read((char*)&w, sizeof(w))) { cout<<w.yearBirth<<" "; if(2016-w.yearBirth<20) d20++; else if(2016-w.yearBirth>20 && 2016-w.yearBirth<30) v20d30++; else if(2016-w.yearBirth>30) b30++; } 

Keep in mind that in this loop you use the non-initialized variable exit .

 bool exit; //... while(exit)