Dane z pliku do struktury nie zapisują się w strukturze ?

0

Ten kod działa - na ekranie pojawiają mi się poprawne wartości w statystykach (zera)

#include <iostream>
#include <fstream>
#include <windows.h>
#include <stdlib.h>
#include <conio.h>

namespace variables
{
    char choice;
}

enum SEX{MALE,FEMALE};

struct Statistics{
   int numberStudents;
   int numberMens;
   int numberWomans;
   float averageClass;
};

struct Student{
   std::string name;
   std::string surname;
   char PESEL[11];
   size_t age;
   SEX sex;
   //float ratings[]   - vector
};

void loadStatistics(Statistics stat)
{
    std::ifstream statFileLoad;
    statFileLoad.open("data.bin",std::ios::binary);
    if(statFileLoad.is_open())
    {
       statFileLoad.read((char*)&stat,sizeof(stat));
       std::cout<<"DZIENNIK KLASY"<<std::endl;
       std::cout<<"====================="<<std::endl;
       std::cout<<"Liczba uczniow: "<<stat.numberStudents<<std::endl;
       std::cout<<"Liczba mezczyzn: "<<stat.numberMens<<std::endl;
       std::cout<<"Liczba kobiet: "<<stat.numberWomans<<std::endl;
       std::cout<<"Srednia klasy: "<<stat.averageClass<<std::endl;
       std::cout<<"====================="<<std::endl;
       statFileLoad.close();

    } else
    {
        statFileLoad.close();

        stat.numberStudents = 0;
        stat.numberMens = 0;
        stat.numberWomans = 0;
        stat.averageClass = 0.0;

        std::ofstream statFileSave("data.bin",std::ios::binary);
        statFileSave.write((const char*)&stat,sizeof(stat));
        statFileSave.close();

        for(int i=0;i<3;i++)
        {
            std::cout<<"Brak zapisanych uczniow! Start za "<<3-i<<" sekundy..."<<std::endl;
            Sleep(1000);
            system("cls");
        }
    }
}

void mainMenu(Statistics stat)
{
    std::cout<<"Dostepne operacje:"<<std::endl;
    std::cout<<"1.Dodaj ucznia"<<std::endl;
    std::cout<<"2.Dodaj ocene"<<std::endl;
    std::cout<<"3.Wyswietl dane ucznia"<<std::endl;
    std::cout<<"4.Usun ucznia"<<std::endl;
    std::cout<<"5.Czyszczenie ocen"<<std::endl;
    std::cout<<"6.WYJSCIE"<<std::endl;
    std::cout<<"=====================";
    variables::choice = getch();

    if(variables::choice=='6')
    {
        exit(0);
    } else std::cout<<"Nieprawidlowy znak!"<<std::endl;
}

int main()
{
    //£ADOWANIE DANYCH
    Statistics statistics;
    loadStatistics(statistics);
    //Student students[];                 - vector

    for(;;)
    {
        //system("cls");
        mainMenu(statistics);
    }

    return 0;
}

Ten już nie - zamiast 0 w statystkach wyświetlają mi się jakieś śmieci.

#include <iostream>
#include <fstream>
#include <windows.h>
#include <stdlib.h>
#include <conio.h>

namespace variables
{
    char choice;
}

enum SEX{MALE,FEMALE};

struct Statistics{
   int numberStudents;
   int numberMens;
   int numberWomans;
   float averageClass;
};

struct Student{
   std::string name;
   std::string surname;
   char PESEL[11];
   size_t age;
   SEX sex;
   //float ratings[]   - vector
};

void loadStatistics(Statistics stat)
{
    std::ifstream statFileLoad;
    statFileLoad.open("data.bin",std::ios::binary);
    if(statFileLoad.is_open())
    {
       statFileLoad.read((char*)&stat,sizeof(stat));
       statFileLoad.close();

    } else
    {
        statFileLoad.close();

        stat.numberStudents = 0;
        stat.numberMens = 0;
        stat.numberWomans = 0;
        stat.averageClass = 0.0;

        std::ofstream statFileSave("data.bin",std::ios::binary);
        statFileSave.write((const char*)&stat,sizeof(stat));
        statFileSave.close();

        for(int i=0;i<3;i++)
        {
            std::cout<<"Brak zapisanych uczniow! Start za "<<3-i<<" sekundy..."<<std::endl;
            Sleep(1000);
            system("cls");
        }
    }
}

void mainMenu(Statistics stat)
{
    std::cout<<"DZIENNIK KLASY"<<std::endl;
    std::cout<<"====================="<<std::endl;
    std::cout<<"Liczba uczniow: "<<stat.numberStudents<<std::endl;
    std::cout<<"Liczba mezczyzn: "<<stat.numberMens<<std::endl;
    std::cout<<"Liczba kobiet: "<<stat.numberWomans<<std::endl;
    std::cout<<"Srednia klasy: "<<stat.averageClass<<std::endl;
    std::cout<<"====================="<<std::endl;
    std::cout<<"Dostepne operacje:"<<std::endl;
    std::cout<<"1.Dodaj ucznia"<<std::endl;
    std::cout<<"2.Dodaj ocene"<<std::endl;
    std::cout<<"3.Wyswietl dane ucznia"<<std::endl;
    std::cout<<"4.Usun ucznia"<<std::endl;
    std::cout<<"5.Czyszczenie ocen"<<std::endl;
    std::cout<<"6.WYJSCIE"<<std::endl;
    std::cout<<"=====================";
    variables::choice = getch();

    if(variables::choice=='6')
    {
        exit(0);
    } else std::cout<<"Nieprawidlowy znak!"<<std::endl;
}

int main()
{
    //£ADOWANIE DANYCH
    Statistics statistics;
    //Student students[];                 - vector
    loadStatistics(statistics);

    for(;;)
    {
        system("cls");
        mainMenu(statistics);
    }

    return 0;
}

Dlaczego tak się dzieje ? Czy w trakcie odczytu danych z pliku program ich nie wprowadza do struktury na stałe tylko na czas otwarcia pliku ?
BTW - czy tworzenie namespace dla zmiennych/stałych jako alternatywa do zmiennych/stałych globalnych to akceptoalna praktyka ?
Tak wiem - powinno się pisać obiektowo,ale na ten moment chcę przerobić inne rzeczy z C++ a obiektówkę zostawić na później.

2

Przesyłaj argumenty przez referencję.

void loadStatistics(Statistics& stat)
void mainMenu(Statistics& stat)

Teraz tworzysz lokalne kopie obiektów, które po wyjściu z funkcji zostają usunięte.

3
Quanti994 napisał(a):

statFileLoad.read((char*)&stat,sizeof(stat));

Na tym można się bardzo łatwo przejechać. Endianness, alignment...

BTW - czy tworzenie namespace dla zmiennych/stałych jako alternatywa do zmiennych/stałych globalnych to akceptoalna praktyka ?

Bez różnicy, to wciąż global. Pytanie, dlaczego to jest zmienna globalna skoro używasz jej tylko w jednej funkcji?

Tak wiem - powinno się pisać obiektowo,ale na ten moment chcę przerobić inne rzeczy z C++ a obiektówkę zostawić na później.

Na szczęście C++ tego nie wymusza. Sam fakt, że coś jest OO nie oznacza, że kod jest z automatu lepszy ;)

0

Tak wiem - powinno się pisać obiektowo

To nie do końca prawda dla C++, sporo obiektowych wzorców popularnych w javie czy .net w c++ uznaje się za antywzorce. Twój kod powinien być blisko danych na których operujesz, fikuśne abstrakcje zostaw innym językom.

0

Dziękuje :)
Mam jeszcze takie pytanie.Otóż chciałabym wprowadzić restrykcje dotyczące zabezpieczenia wprowadzenia nieprawidłowych danych dot. imienia i nazwiska (dozwolone tylko litery),PESEL (tylko liczby) oraz ocen (tylko liczby) bez potrzeby wywalania komunikatu do konsoli.

Czy zablokowanie klawiatury przez BlockInput a następnie dozwolenie wybranych klawiszy przez WM_KEYDOWN ma sens ? Chodzi mi o uzyskanie efektu,gdzie w trakcie wpisywania imienia użytkownik w przypadku nacisniecia klawisza innego niz litera ani nie wprowadzi tego na ekran,ani nie otrzyma komunikatu o bledzie - po prostu nic sie nie stanie bo konsola nie zareaguje na ten klawisz

1

na ten moment globalna - wraz z rozwojem projektu przekonam się czy warto ją tam zostawić czy zmienić w lokalną zmienną (kod zawsze optymalizuje i poprawiam na końcu : P)

Nie "przekonasz się", ale masz mieć odruch dawania zmiennych lokalnych. Co może się stać ze wzrostem projektu? Że drugi moduł będzie jej uzywał? To pełna patologia. Patologię potwierdza, że robisz te namespace (plus o nazwie "variables" a nie dziedzinowej), czyli coś ci dzwoni, tylko nie chcesz tego słyszeć.

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