[C++] Książka adresowa - wczytywanie danych - wektor struktur

0

Cześć, mam za zadanie przerobić swój program "Książka adresowa" tak, aby zamiast do tablic struktur, zapisywał dane do wektora. Dodatkowo, dane mają być zapisywane w jednej linii, przedzielone znakiem "|". Niestety, po wpisaniu danych pierwszej osoby, w trakcie wpisywania danych drugiej osoby program kończy działanie. Po ponownym włączeniu programu, nie wyświetla się już menu tylko program wyłącza się z błędem. Problem występuje prawdopodobnie podczas wczytywania danych do struktury. Pytanie więc, jak zmienić funkcje aby odczytywała wszystkie dane z jednej linii pliku tekstowego. Poniżej mój kod.

#include <iostream>
#include <fstream>
#include <windows.h>
#include <cstdlib>
#include <vector>

using namespace std;

struct Znajomy
{
    int id = 0;
    string imie, nazwisko, nr_tel, adresEmail, adresZamieszkania;
};

bool szukajZnaku ( string tekst, char szukanyZnak )
{
    size_t znalezionaPozycja = tekst.find ( szukanyZnak );
    if( znalezionaPozycja == string::npos )
    {
       return false;
    }
    else
           return true;
}

int dodanieDanych ( vector <Znajomy> znajomi, int iloscZnajomych )
{
    Znajomy osoba;

    string daneAdresata;

    cout << "Podaj imie znajomego: ";
    cin >> osoba.imie;
    cout << "Podaj nazwisko znajomego: ";
    cin >> osoba.nazwisko;

    int i = 0;
    while ( i < iloscZnajomych )
    {
        if (( znajomi[i].imie == osoba.imie ) && ( znajomi[i].nazwisko == osoba.nazwisko ))
        {
            cout << "Znajomy o takich danych juz istnieje. Wpisz inne dane: " << endl;
            cout << "Podaj imie znajomego: ";
            cin >> osoba.imie;
            cout << "Podaj nazwisko znajomego: ";
            cin >> osoba.nazwisko;
        }
        else
        {
            i++;
        }
    }
    cout << "Podaj numer telefonu znajomego: ";
    cin.sync();
    getline ( cin, osoba.nr_tel );
    cout << "Podaj adres e-mail znajomego: ";
    cin >> osoba.adresEmail;
    while( !szukajZnaku ( osoba.adresEmail, '@' ))
        {
        cout << "Nieprawidlowy adres e-mail. Podaj adres e-mail znajomego: ";
        cin >> osoba.adresEmail;
        }
    cout << "Podaj adres zamieszkania znajomego: ";
    cin.ignore();
    getline ( cin, osoba.adresZamieszkania );
    osoba.id = iloscZnajomych + 1;
    znajomi.push_back(osoba);

    fstream plik;
    plik.open ( "ksiazkaAdresowa.txt", ios::out | ios::app );

    if ( plik.good() == true )
    {
    osoba.id = iloscZnajomych + 1;
    plik << znajomi[iloscZnajomych].id << "|";
    plik << znajomi[iloscZnajomych].imie << "|";
    plik << znajomi[iloscZnajomych].nazwisko << "|";
    plik << znajomi[iloscZnajomych].nr_tel << "|";
    plik << znajomi[iloscZnajomych].adresEmail << "|";
    plik << znajomi[iloscZnajomych].adresZamieszkania << "|" << endl;

    plik.close();
    }
    else
    {
        cout << "Nie udalo sie otworzyc pliku i zapisac do niego danych" << endl;
        Sleep(1000);
    }

    cout << "Dane znajomego zostaly dodane" << endl;
    Sleep(1000);
    return iloscZnajomych + 1;
}

int wczytywanieZnajomychDoStruktury(vector <Znajomy> znajomi)
{
    int iloscZnajomych = 0;
    string linia;
    int nr_linii = 1;
    int numerKontaktu = 0;
    fstream plik;

    plik.open ( "ksiazkaAdresowa.txt", ios::in );

    if(plik.good() == false)
    {
        plik.open ( "ksiazkaAdresowa.txt", ios::out );
        plik.close();
    }
    else
    {
        while ( getline ( plik, linia ))
        {
            if ( nr_linii == 2 )
            {
                numerKontaktu++;
                nr_linii = 1;
            }

            switch ( nr_linii )
            {
            case 1:
                znajomi[numerKontaktu].id = atoi(linia.c_str());
                break;
            case 2:
                znajomi[numerKontaktu].imie = linia;
                break;
            case 3:
                znajomi[numerKontaktu].nazwisko = linia;
                break;
            case 4:
                znajomi[numerKontaktu].nr_tel = linia;
                break;
            case 5:
                znajomi[numerKontaktu].adresEmail = linia;
                break;
            case 6:
                znajomi[numerKontaktu].adresZamieszkania = linia;
                break;
            }
            nr_linii++;
        }

        iloscZnajomych = ++numerKontaktu;

        plik.close();
    }
    return iloscZnajomych;
}

void wyswietlZnajomych ( vector <Znajomy> znajomi, int iloscZnajomych )
{
    string imie;
    fstream plik;
    system ( "cls" );

    int ile = 0;

    for (int i = 0; i < iloscZnajomych; i++)
    {
        if(znajomi[i].id >= 1)
        {
            ile++;
            cout << znajomi[i].id << "|";
            cout << znajomi[i].imie << "|" << znajomi[i].nazwisko << "|";
            cout << znajomi[i].nr_tel << "|";
            cout << znajomi[i].adresEmail << "|";
            cout << znajomi[i].adresZamieszkania << "|";
            cout << endl;
        }
    }
    if ( ile <= 0 )
    {
        cout << "Brak znajomych w ksiazce adresowej" << endl;
    }
    system ( "pause" );
}

int main()
{
    vector <Znajomy> znajomi;
    int idZnajomego = 0;
    int iloscZnajomych = 0;

    char wybor;

    iloscZnajomych = wczytywanieZnajomychDoStruktury ( znajomi );

    while(true)
    {
        if( idZnajomego == 0 )
        {
            system ( "cls" );
            cout << "1. Dodaj dane znajomego" << endl;
            cout << "2. Wyszukaj znajomych po imieniu" << endl;
            cout << "3. Wyszukaj znajomych po nazwisku" << endl;
            cout << "4. Wyswietl wszystkich znajomych" << endl;
            cout << "5. Usun adresata" << endl;
            cout << "5. Edytuj adresata" << endl;
            cout << "9. Zakoncz program" << endl;
            cout << endl;
            cout << "Twoj wybor: ";
            cin >> wybor;

            if ( wybor == '1' )
            {
                system ( "cls" );
                iloscZnajomych = dodanieDanych ( znajomi, iloscZnajomych );
            }
            else if ( wybor == '2' )
            {
               //szukaniePoImieniu ( znajomi, iloscZnajomych );
            }
            else if ( wybor == '3' )
            {
                //szukaniePoNazwisku ( znajomi, iloscZnajomych );
            }
            else if ( wybor == '4' )
            {
                system ( "cls" );
                wyswietlZnajomych ( znajomi, iloscZnajomych );
            }
            else if ( wybor == '5' )
            {
                //system ( "cls" );
                ;
            }
            else if ( wybor == '6' )
            {
                //system ( "cls" );
                ;
            }
            else if ( wybor == '9' )
            {
                system ( "cls" );
                cout << "Zakonczono dzialanie programu";
                cout << endl;
                exit(0);
            }
        }
    }

    return 0;
}
2

Skoro jesteś już bardziej zaawansowany niż początkujący,

  • pomyśl o zawarciu tego magazynu w klasie. Takie proceduralne jest dość brzydkie, i niewiele dobrego na tym się nauczysz.
  • masz z czapy kopiowany argument 'ilość' - pachnie jak C
1

W Twoim projekcie jest kilka elementów, które mogą sprawiać problem (nie wiem czy zauważyłem wszytskie):

  1. dodałeś użycie vectora, ale w sumie nie korzystasz z jego dobrodziejstw np. nie potrzrebujesz mieć oddzielnej zmiennej do przechowywania liczby danych w
    vectorze, ponieważ vector posiada metodę size().
  2. Funkcja od wczytywania znajomych też w sumie nie jest gotowa na dane w takim formacie jak przedstawiłeś. Skoro każda linia zawiera dane rozdzielone znakiem | to gdzieś powinieneś mieć funkcjonalność dzielenia tego stringa na poszczególne dane. Nie wiem czy możesz używać zewnętrznych bibliotek, ale boost posiada taką funkcję - nazywa się split i służy właśnie do rozdzielnia stringa na mniejsze zgodnie z podanym separatorem.
2

W funkcji

int wczytywanieZnajomychDoStruktury(vector <Znajomy> znajomi)

wczytujesz dane do wektora znajomi który utworzony został lokalnie i po wyjściu z funkcji przestaje istnieć wraz z wszystkimi wczytanymi danymi.
Tutaj musisz przekazać wektor przez referencję (&) a nie przez wartość.

int wczytywanieZnajomychDoStruktury( vector<Znajomy>& znajomi )
0

Witam,

Przypinam się do tematu, chciałem zrobić podobny program jak kolega wyżej, ale przy wyświetlaniu znajomych cały czas otrzymuję komunikat o błędzie "Instrukcja w 0x000000000040170F odowołałą się do pamięci pod adresem 0x0000000000000. Pamięć nie może być read." Czy można prosić o wskazanie co powinienem poprawić?

#include <iostream>
#include <vector>

using namespace std;

struct Adresat
{
    int id = 0;
    string imie, nazwisko, numerTelefonu, email, adres;
};

int dodajUzytkownika(vector <Adresat> adresaci, int iloscUzytkowikow)
{
    Adresat obiekt;

    obiekt.id = iloscUzytkowikow +1;
    cout << "Podaj imie:";
    cin >> obiekt.imie;
    cout << "Podaj nazwisko:";
    cin >> obiekt.nazwisko;
    cout << "Podaj numer telefonu:";
    cin.sync();
    getline(cin, obiekt.numerTelefonu);
    cout << "Podaj adres:";
    cin.sync();
    getline(cin, obiekt.adres);
    cout << "Podaj e-mail:";
    cin >> obiekt.email;

    adresaci.push_back(obiekt);

    iloscUzytkowikow++;
    return iloscUzytkowikow;
}

void wczytywanieUzytkownikow(vector <Adresat> adresaci, int iloscUzytkowikow)
{
    system("cls");
    for (int i = 0; i<=iloscUzytkowikow-1; i++)
    {
        cout << "id uzytkownika to : " << adresaci[i].id << endl;
        cout << "imie uzytkownika to : " << adresaci[i].imie << endl;
        cout << "nazwisko uzytkownika to : " << adresaci[i].nazwisko << endl;
        cout << "numerTelefonuefon uzytkownika to : " << adresaci[i].numerTelefonu << endl;
        cout << "email uzytkownika to : " << adresaci[i].email << endl;
        cout << "adres uzytkownika to : " << adresaci[i].adres << endl;
        cout << "-------------------------" << endl;
    }
    system("pause");
}

int main()
{
    vector<Adresat> adresaci;
    int iloscUzytkowikow = 0;
    char wybor;

    while (true)
    {
        system("cls");
        cout << "1. Zapisz dane" << endl;
        cout << "4. Wczytaj wszytskie dane" << endl;
        cout << "5. Zakonczenie programu" << endl;
        cin >> wybor;

        if (wybor == '1')
        {
            iloscUzytkowikow = dodajUzytkownika(adresaci, iloscUzytkowikow);
        }
        else if (wybor == '4')
        {
            system("pause");
            wczytywanieUzytkownikow(adresaci, iloscUzytkowikow);
        }
        else if (wybor == '5')
        {
            exit(0);
        }
    }
    return 0;
}

0

W funkcji wczytywanieUzytkownikow przekazany wektor ma rozmiar 0
Ba w obu funkcjach przekazany wektor to kopia!

0

Dziękuję Ci za wskazanie błędu, lecz pomimo 2 h nadal nie mogę poradzić sobie jak przekazywać i odczytywać oryginał. Patrzyłem na rozwiązania innych osób i nadal nie mogę dojść do tego co mógłbym poprawić.

2
void wczytywanieUzytkownikow(vector<Adresat> &adresaci)

Nie potrzebujesz ilości użytkowników bo to adresaci.size()

0

@_13th_Dragon: Dziękuję, teraz wszystko jest jasne, program działa :)

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