2
#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 На скриншоте видно, что 5 прочиталась программой 2 раза. Почему так произошло?

  • Классика. Флаг eof ставится после неудачного чтения. Поэтому сначала читаем потом поверяем. У вас наоборот. – pavel Dec 15 '16 at 21:11
  • Как тогда переписать данный отрезок? Используя do while получил тот же результат – Максим Калани Dec 15 '16 at 21:15
  • Дубликат? http://ru.stackoverflow.com/q/421083/10105 – VladD Dec 15 '16 at 21:47
  • @VladD C дубликатами странная ситуация, если вдуматься :) С одной стороны - проблема явно та же, с другой - каждый задает вопрос по-своему. Чтобы задать вопрос, как в указанной вами ссылке, нужно знать если не весь ответ, то половину... – Harry Dec 16 '16 at 03:30
  • @Harry: Ну, это как бы канонический вопрос для того, чтобы делать другие дубликатами к нему. – VladD Dec 16 '16 at 06:50

1 Answers1

2

У вас неверно составлен цикл чтения из файла

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++;
}

Состояние eof не наступает сразу же после того, как вы прочитали последнюю запись. Оно наступает после того, как вы попытаетесь прочитать несуществующую запись после последней записи файла.

Поэтому когда последняя запись уже прочитана, вы, тем не менее, опять попадете внутрь цикла, так как условие цикла будет истинным.

На этом предложении

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

произойдет ситуация с eof, однако вы все равно пытаетесь вывести данные из объекта 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++;

Правильно будет организовать цикл, например, следующим образом

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++;
}

Имейте в виду, что в этом цикле вы используете не инициализированную переменную exit.

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