Wczytywanie z pliku do struktury przy pomocy getline

0

Witam, stworzylem program ktory tworzy strukturalna tablice typu student{nazwisko, imie, wiek}, nastepnie w zaleznosci od wyboru uzytkownika prosi o wprowadzenie danych, zapisuje je do pliku, lub odczytuje je z tegoz pliku. Wszystko smiga ladnie dopoki zmienne strukturalne sa typu string, natomiast gdy wiek zrobie typu int w zasadzie dziala dalej, ale po odczytaniu wszystkich danych z pliku i zapisie do struktury na koncu dopisuje '0'.
Skonczyly mi sie pomysly o co moze chodzic.
Dzialanie programu jest intuicyjne, jesli ktos z Was sie zlituje i skompiluje u siebie i wprowadzi 1 - 2 pozycje, to bedzie widac, gdzie lezy problem. Dzieki z gory. (Funkcja szukaj ktora jest 1sza pozycja w menu dopiero bedzie.)

[Edit] Jezeli sposob w jaki umiescilem kod lub zadalem pytanie jest niezgodny z jakas niepisana zasada, co sprawia ze nikt nawet na niego nie spojrzy prosze o zwrocenie mi uwagi.

Kod zrodlowy:


#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <windows.h>
#include <string>
#include <fstream>
#define LICZBA_STUDENTOW 20

using namespace std;

struct student {
    string nazwisko;
    string imie;
    int wiek;
} delikwent[LICZBA_STUDENTOW];

fstream plik;

void wprowadz(int*);
void odczyt_z_pliku(int*);

int main()
{
    int i = 0;
    while (1) {
        system("cls");
        printf("\tMENU\n");
        printf("---------------------------\n");
        int opcja;
        printf("1- wyszukiwanie delikwenta\n");
        printf("2- wprowadzanie delikwentow\n");
        printf("3- odczyt listy delikwentow z pliku\n");
        printf("4- koniec\n");
        printf("---------------------------\n");
        printf("\nPodaj wybor:\n");
        scanf("%d", &opcja);
        switch (opcja) {
        case (1):
            //szukaj();
            break;
        case (2):
            wprowadz(&i);
            break;
        case (3):
            odczyt_z_pliku(&i);
            break;
        case (4):
            exit(1);
            break;
        default:
            printf("zle wybrana opcja\n");
            Sleep(2000);
            break;
        }
    }
    return 0;
}

//void szukaj(void){}

void wprowadz(int* i)
{

    char wybor;
    do {
        system("cls");
        plik.open("Studenci.txt", ios::out | ios::app);
        cin.get();
        cout << "Podaj nazwisko:\n";
        getline(cin, delikwent[*i].nazwisko);
        cout << "Podaj imie:\n";
        getline(cin, delikwent[*i].imie);
        cout << "Podaj wiek:\n";
        cin >> delikwent[*i].wiek;
        plik << delikwent[*i].nazwisko << "\n" << delikwent[*i].imie << "\n" << delikwent[*i].wiek << "\n";
        plik.close();
        cout << "Czy chcesz wprowadzic nastepna osobe?\n\t";
        cout << "TAK(T)\tNIE(N)\n\t";
        cin >> wybor;
        (*i)++;
    } while ((wybor == 't') && (*i < LICZBA_STUDENTOW));
}

void odczyt_z_pliku(int* i)
{
    plik.open("Studenci.txt", ios::in);
    if (plik.good()) {
        string linia;
        *i = 0;
        int nr_linii = 1;
        while (getline(plik, linia)) {
            switch (nr_linii) {
            case 1:
                delikwent[*i].nazwisko = linia;
                break;
            case 2:
                delikwent[*i].imie = linia;
                break;
            case 3:
                delikwent[*i].wiek = atoi(linia.c_str());
                break;
            }
            if (nr_linii == 3) {
                nr_linii = 0;
                (*i)++;
            }
            nr_linii++;
        }
    }
    else
        cout << "Plik nie istnieje!\n";
    system("cls");

    for (int j = 0; j <= *i; j++) {
        if ((*i) == 0) {
            puts("Nie wprowadziles jeszcze nikogo!");
            Sleep(2000);
            break;
        }
        cout << delikwent[j].nazwisko << " " << delikwent[j].imie << " " << delikwent[j].wiek << "\n";
    }
    if (*i) {
        system("PAUSE");
    }
    plik.close();
}

0

Po przemysleniach stawiam na pomysl ze getline do inta wpisuje 0 z EOF, ale jestem poczatkujacy i moze wlasnie napisalem glupote. :)
Dla jasności wkleje skrocony kod, ktory stanowi problem. Nalezy jedynie w katalogu z plikiem main utworzyc plik "Studenci.txt" i wpisac do niego dane w formacie:
napis
napis
liczba
(opcjonalnie dalej)
napis
napis
liczba


#include <iostream>
#include <stdio.h>
#include <cstdlib>
#include <windows.h>
#include <string>
#include <fstream>
#define LICZBA_STUDENTOW 20

using namespace std;

struct student {
    string nazwisko;
    string imie;
    int wiek;
} delikwent[LICZBA_STUDENTOW];

fstream plik;

void odczyt_z_pliku(int*);

int main()
{
    int i = 0;
    odczyt_z_pliku(&i);

    return 0;
}

void odczyt_z_pliku(int* i)
{
    plik.open("Studenci.txt", ios::in);
    if (plik.good()) {
        string linia;
        *i = 0;
        int nr_linii = 1;
        while (getline(plik, linia)) {
            switch (nr_linii) {
            case 1:
                delikwent[*i].nazwisko = linia;
                break;
            case 2:
                delikwent[*i].imie = linia;
                break;
            case 3:
                delikwent[*i].wiek = atoi(linia.c_str());
                break;
            }
            if (nr_linii == 3) {
                nr_linii = 0;
                (*i)++;
            }
            nr_linii++;
        }
    }
    else
        cout << "Plik nie istnieje!\n";
    system("cls");

    for (int j = 0; j <= *i; j++) {
        if ((*i) == 0) {
            puts("Nie wprowadziles jeszcze nikogo!");
            Sleep(2000);
            break;
        }
        cout << delikwent[j].nazwisko << " " << delikwent[j].imie << " " << delikwent[j].wiek << "\n";
    }
    if (*i) {
        system("PAUSE");
    }
    plik.close();
}

1
Legion616 napisał(a):

Czyżby zadanie wszystkich przerosło?

Nie wiem jak innych, ale mnie przerasta czytanie niekolorowanego kodu z beznadziejnymi wcięciami. O kiepskiej jakości kodu i dziwnych konstrukcjach już nie mówię, bo jako początkujący niejako masz prawo do tego.

Wrzuć kod tutaj: http://format.krzaq.cc style file, a potem wrzuć do posta (zmodyfikuj istniejący) pamiętając o kolorowaniu: Formatowanie treści postów na forum to może ktoś będzie chciał to czytać.

0

Fakt, dzieki za zwrocenie uwagi, generalnie morze nauki jeszcze przede mna, a siedzialem nad tym teraz pare godzin i w desperacji wrzucilem na szybko.
(Edit) Prosze, poprawiony optycznie kod. A za zwrocenie uwagi na "kiepska jakosc i dziwne konstrukcje" tez sie nie obraze, w koncu nauka polega na sluchaniu rad od bardziej doswiadczonych.

0
#define LICZBA_STUDENTOW 20

Do zdefiniowania stałych używaj

const int LICZBA_STUDENTOW = 20;
delikwent[LICZBA_STUDENTOW];
fstream plik;

Nie używaj zmiennych globalnych.

void odczyt_z_pliku(int* i)

Po co ten argument funkcji? W dodatku jako wskaźnik?

puts("Nie wprowadziles jeszcze nikogo!");

Bądź konsekwentny, jak używasz cout to nie puts.

if (*i)

*i jest typu int, a nie bool, więc nie używaj go jak bool. W tym przypadku chcesz sprawdzić czy ta wartość jest większa niż 0, a nie czy jest prawdziwa, więc sformułuj to w kodzie w odpowiedni sposób

if (*i > 0)
for (int j = 0; j <= *i; j++)

Jeżeli w pliku były dane 20 osób, to *i ma wartość 20. Dla j równego 20 odwołanie się do elementu delikwent[j] jest poważnym błędem. Generalnie jeżeli w warunku pętli masz <= to zastanów się 2 razy czy na pewno to nie błąd, bo większość rzeczy w C++ jest tak zaprojektowana, że najczęściej jest <.

Ta funkcja odczyt_z_pliku() jest niepotrzebna taka długa. Wszystko czego potrzebujesz to:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

const int STUDENTS_NUMBER = 20;

struct Student
{
	string name;
	string surname;
	int age;
};

void readFromFile(Student delinquents[])
{
	int i = 0;

	ifstream input("in.txt");
	while (!input.eof())
	{
		input >> delinquents[i].name >> delinquents[i].surname >> delinquents[i].age;
		++i;
	}
}

void print(Student delinquents[])
{
	for (int i = 0; i < STUDENTS_NUMBER; ++i)
	{
		cout << delinquents[i].name << " " << delinquents[i].surname << " " << delinquents[i].age << endl;
	}
}

int main()
{
	Student delinquents[STUDENTS_NUMBER];
	readFromFile(delinquents);
	print(delinquents);

	return 0;
}
0

Ok dzieki. Powod dla ktorego przekazywalem argument '*i' jest taki, ze na poczatku program zapisywal tylko do RAMu i z RAMu pobieral dane, tak wiec potrzebowalem jakiegos licznika studentow. Jako ze przy zapisie do pliku wskaznik zawsze laduje na koncu pliku to teraz powywalalem wszystkie 'i' z argumentow i dziala dobrze. Co do tego "i <= j" to zwykly pospiech a pozniej przeoczenie, wiem i rozumiem ze powinno byc "i < j", mimo wszystko taki blad, ze wstyd. Jak zmienilem na poprawna wersje owe zagadkowe '0' zniknelo a wiec tu lezal problem.
Jedyne co, to Twoja impementacja funkcji odczyt_z_pliku() u mnie nie dziala, byc moze dlatego ze mam powprowadzane podwojne imiona i nazwiska, stad tez moje kombinowanie z getline.
W kazdym razie problem rozwiazany, wielkie dzieki, pozdrawiam.

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