W trakcie odczytu pliku bin program sie sypie

0

Cześć.
Zaczęłam uczyć się programowania (tydzień) także proszę o wyrozumiałość.
Stworzyłam programik do zapisywania danych pracowników do pliku binarnego.Dane te są przechowywane w strukturze.Używam wskaźnikóww celu szybszego działania programu.

Program kompiluje się,plik powstaje jednak próba odczytu danych pracowników z pliku binarnego kończy się tak:
https://iv.pl/image/GrdK8ms

I nie wiem co jest przyczyną.W pliku main wskaźnik za każdym razem ustawiam na tablicę struktur,aby tworzenie/zapis/odczyt zawsze zaczynał się od 0 indeksu tablicy struktur.
Przepraszam za jakość kodu,ale jestem początkująca w C++

binarDatWorker.h

#ifndef BINARDATWORKER_H
#define BINARDATWORKER_H
#include <iostream>
#include <string>
#include <fstream>
#include <conio.h>

using namespace std;

enum SEX {MALE=1,FEMALE=2};

struct dataPerson{
    string name;
    string surname;
    unsigned short age;
    SEX sex;
    char PESEL[11];
};

void checkSex(dataPerson *n_indi);
void setPESEL(dataPerson *n_indi);
void setPerson(dataPerson *n_indi);
void getPerson(dataPerson *n_indi);
void savePerson(dataPerson *n_indi);
void loadPerson(dataPerson *n_indi);

#endif // BINARDATWORKER_H

binarDatWorker.cpp

#include "binarDatWorker.h"

void checkSex(dataPerson *n_indi)
{
    int numbSex = n_indi->PESEL[10] - '0'; //W tabeli ASCII wartość znaku 0 jest równa 48. Następne znaki cyfr do 9 mają wartości po kolei 49, 50, ..., 57. Więc gdy odejmiemy od nich wartość znaku 0 (48) to zostanie nam odpowiednia cyfra.
    if(numbSex%2==0) n_indi->sex=FEMALE; else n_indi->sex=MALE;
}

void setPESEL(dataPerson *n_indi)
{
    for(int i=0;i<11;i++)
    {
        n_indi->PESEL[i] = getch();
        cout<<n_indi->PESEL[i];
    }
}

void setPerson(dataPerson *n_indi)
{
    for(int i=0;i<3;i++)
    {
        cout <<"----------------------------------------"<<endl;
        cout <<"Podaj imie pracownika nr "<<i+1<<": ";
        cin >>n_indi->name;
        cout <<"Podaj nazwisko pracownika nr "<<i+1<<": ";
        cin >>n_indi->surname;
        cout <<"Podaj wiek pracownika nr "<<i+1<<": ";
        cin >>n_indi->age;
        cout <<"Podaj PESEL pracownika nr "<<i+1<<": ";
        setPESEL(n_indi);
        checkSex(n_indi);
        cout<<endl;
        n_indi++;
    }

}

void savePerson(dataPerson *n_indi)
{
    ofstream save("database.bin",ios::binary);

    for(int i=0;i<3;i++)
    {
        save.write(n_indi->name.c_str(),n_indi->name.size()+1);
        save.write(n_indi->surname.c_str(),n_indi->surname.size()+1);
        save.write((const char*)&n_indi->age,sizeof n_indi->age);
        for(int j=0; j<10; j++) {save.write(&n_indi->PESEL[j],sizeof n_indi->PESEL[j]);}
        save.write((const char*)&n_indi->sex,sizeof n_indi->sex);
        n_indi++;
    }

    save.close();
}

void loadPerson(dataPerson *n_indi)
{
    ifstream open("database.bin",ios::binary);

    for(int i=0;i<3;i++)
    {
        getline(open,n_indi->name,'\0');
        getline(open,n_indi->surname,'\0');
        open.read((char*)&n_indi->age,sizeof &n_indi->age);
        for(int j=0; j<10; j++) {open.read(&n_indi->PESEL[j],sizeof &n_indi->PESEL[j]);}
        open.read((char*)&n_indi->sex,sizeof &n_indi->sex);
        n_indi++;
    }

    open.close();
}

void getPerson(dataPerson *n_indi)
{
    cout<<"=================================================="<<endl;
    cout<<"LISTA PRACOWNIKOW: "<<endl;

    for(int i=0;i<3;i++)
    {
        cout <<"----------------------------------------"<<endl;
        cout <<"Imie pracownika nr "<<i+1<<": "<<n_indi->name<<endl;
        cout <<"Nazwisko pracownika nr "<<i+1<<": "<<n_indi->surname<<endl;
        cout <<"Wiek pracownika nr "<<i+1<<": "<<n_indi->age<<endl;
        if(n_indi->sex==1) cout <<"Plec pracownika nr "<<i+1<<": Mezczyzna"<<endl; else cout <<"Plec pracownika nr "<<i+1<<": Kobieta"<<endl;
        cout <<"PESEL pracownika nr "<<i+1<<": ";
        for(int i=0;i<11;i++){cout<<n_indi->PESEL[i];}
        cout<<endl;
        n_indi++;
    }
}

main.cpp

#include "binarDatWorker.h"

int main()
{
    dataPerson persons[3];
    dataPerson *indi;

    indi = persons;
    setPerson(indi);

    indi = persons;
    savePerson(indi);

    indi = persons;
    loadPerson(indi);

    indi = persons;
    getPerson(indi);

    return 0;
}
4
        open.read((char*)&n_indi->age,sizeof &n_indi->age);
        for(int j=0; j<10; j++) {open.read(&n_indi->PESEL[j],sizeof &n_indi->PESEL[j]);}

pochrzaniłaś użycie sizeof

Swoją drogą nikt nie zapisuje i odczytuje danych w ten sposób.

2

Serializuj to jakoś porządnie, np. do json albo sqlite, zamiast się bawić w pół-binarny zapis.

for(int j=0; j<10; j++) {open.read(&n_indi->PESEL[j],sizeof &n_indi->PESEL[j]);}

Tutaj masz problem, bo zamiat wczytywać znak, wczytujesz ich 4 albo 8 (sizeof wskaźnika). sizeof(char) to zawsze 1, więc nie masz powodu aby to sprawdzać. No i PESEL ma 11 znaków, a nie 10.

1

Dlaczego proceduralne funkcje, a nie metody w klasie?
Mój okulista mnie opieprzy, że to czytam

0

Program działa!
Dziękuje za pomoc!

binarDatWorker.h

#ifndef BINARDATWORKER_H
#define BINARDATWORKER_H
#include <iostream>
#include <string>
#include <fstream>
#include <conio.h>

using namespace std;

enum SEX {MALE=1,FEMALE=2};

struct dataPerson{
    string name;
    string surname;
    unsigned short age;
    SEX sex;
    char PESEL[11];
};

void checkSex(dataPerson *n_indi);
void setPESEL(dataPerson *n_indi);
void setPerson(dataPerson *n_indi);
void getPerson(dataPerson *n_indi);
void savePerson(dataPerson *n_indi);
void loadPerson(dataPerson *n_indi);

#endif // BINARDATWORKER_H

binarDatWorker.cpp

#include "binarDatWorker.h"

void checkSex(dataPerson *n_indi)
{
    int numbSex = n_indi->PESEL[10] - '0'; //W tabeli ASCII wartoœæ znaku 0 jest równa 48. Nastêpne znaki cyfr do 9 maj¹ wartoœci po kolei 49, 50, ..., 57. Wiêc gdy odejmiemy od nich wartoœæ znaku 0 (48) to zostanie nam odpowiednia cyfra.
    if(numbSex%2==0) n_indi->sex=FEMALE; else n_indi->sex=MALE;
}

void setPESEL(dataPerson *n_indi)
{
    for(int i=0;i<11;i++)
    {
        n_indi->PESEL[i] = getch();
        cout<<n_indi->PESEL[i];
    }
}

void setPerson(dataPerson *n_indi)
{
    for(int i=0;i<3;i++)
    {
        cout <<"----------------------------------------"<<endl;
        cout <<"Podaj imie pracownika nr "<<i+1<<": ";
        cin >>n_indi->name;
        cout <<"Podaj nazwisko pracownika nr "<<i+1<<": ";
        cin >>n_indi->surname;
        cout <<"Podaj wiek pracownika nr "<<i+1<<": ";
        cin >>n_indi->age;
        cout <<"Podaj PESEL pracownika nr "<<i+1<<": ";
        setPESEL(n_indi);
        checkSex(n_indi);
        cout<<endl;
        n_indi++;
    }

}

void savePerson(dataPerson *n_indi)
{
    ofstream save("database.bin",ios::binary);

    for(int i=0;i<3;i++)
    {
        save.write(n_indi->name.c_str(),n_indi->name.size()+1);
        save.write(n_indi->surname.c_str(),n_indi->surname.size()+1);
        save.write((const char*)&n_indi->age,sizeof n_indi->age);
        for(int j=0; j<11; j++) {save.write(&n_indi->PESEL[j],sizeof(char));}
        save.write((const char*)&n_indi->sex,sizeof n_indi->sex);
        n_indi++;
    }

    save.close();
}

void loadPerson(dataPerson *n_indi)
{
    ifstream open("database.bin",ios::binary);

    for(int i=0;i<3;i++)
    {
        getline(open,n_indi->name,'\0');
        getline(open,n_indi->surname,'\0');
        open.read((char*)&n_indi->age,sizeof n_indi->age);
        for(int j=0; j<11; j++) {open.read(&n_indi->PESEL[j],sizeof(char));}
        open.read((char*)&n_indi->sex,sizeof &n_indi->sex);
        n_indi++;
    }

    open.close();
}

void getPerson(dataPerson *n_indi)
{
    cout<<"=================================================="<<endl;
    cout<<"LISTA PRACOWNIKOW: "<<endl;

    for(int i=0;i<3;i++)
    {
        cout <<"----------------------------------------"<<endl;
        cout <<"Imie pracownika nr "<<i+1<<": "<<n_indi->name<<endl;
        cout <<"Nazwisko pracownika nr "<<i+1<<": "<<n_indi->surname<<endl;
        cout <<"Wiek pracownika nr "<<i+1<<": "<<n_indi->age<<endl;
        if(n_indi->sex==1) cout <<"Plec pracownika nr "<<i+1<<": Mezczyzna"<<endl; else cout <<"Plec pracownika nr "<<i+1<<": Kobieta"<<endl;
        cout <<"PESEL pracownika nr "<<i+1<<": ";
        for(int i=0;i<11;i++){cout<<n_indi->PESEL[i];}
        cout<<endl;
        n_indi++;
    }
}

main.cpp

#include "binarDatWorker.h"

int main()
{
    dataPerson persons[3];
    dataPerson *indi;

    indi = persons;
    setPerson(indi);

    indi = persons;
    savePerson(indi);

    indi = persons;
    loadPerson(indi);

    indi = persons;
    getPerson(indi);

    return 0;
}
0

Jest takie prawo Murphiego "jeśli wydaje Ci się, że coś działa, to jesteś źle poinformowany/a"

Load masz niekompatybilne z Save (kilka zagadnień, nie mam czasu)
A szczególnie zapis binarny string.size() jest błędny (nie bardzo jest to jak odwrotnie odczytać)

nazwy funkcji nie odpowiadają rzeczywistości np niektóre setXxxxx powinny się nazywa readXxxx

1

Nazwy funkcji trochę nie opowiadają temu co one faktycznie robią. Np void setPerson(dataPerson *n_indi) sugeruje zapisanie jednego rekordu a nie kilku. Lepiej byłoby to nazwać np. tak:

void savePersons(const dataPerson* persons, const size_t size) {
    for (size_t i=0; i < size; i++) {
    //...
    }
}

int main() {
    const size_t PERSONS_SIZE = 3;
    dataPerson persons[PERSONS_SIZE];
    savePersons(persons, PERSONS_SIZE);
}

Przy okazji pozbędziesz się magicznej liczy 3, którą trzeba zmieniać w wielu miejscach przy zmianie wielkości tablicy.

Płeć i wiek to pola redundantne, które można odczytać z PESELu. Tzn. nie jest to jakieś zło, bo kosztem pamięci pozbywamy się obliczania płci i wieku przy każdym dostępie do pola. Jednak serializowanie tego do pliku nie jest potrzebne. Szkoda marnować miejsce w pliku na np. wiek, kiedy po jakimś czasie ta dana na pewnie nie jest aktualna.

btw, dataPerson bardziej odpowiada zmiennej niż typie danych. Według mnie lepiej byłoby to nazwać DataPerson albo po prostu Person. Lub też dataPerson_s

1 użytkowników online, w tym zalogowanych: 0, gości: 1