[C++] działanie na tablicy dynamicznej struktur

Witam.

Mam problem z zadaniem, które brzmi tak: “stworzyć tablicę dynamiczną struktur o wielkości n, a następnie za pomocą funkcji dodawać, kasować i wyświetlać elementy.” Struktura wygląda tak jak w kodzie.

Kompilator nie wyświetla żadnego błędu, ale gdy próbuję wykonać dowolną operację na tablicy w funkcji (np. cout << tablica[numer].imie; albo przypisanie wartości), program zawiesza się.

#include 

#include 


using namespace std;


struct student

{

       string imie;

       string nazwisko;

       float srednia_ocen;

       int stypendium;

       int wiek;

};


student *tablica;

int n;


void dodaj();

void kasuj();

void wyswietl();





int main()

{

    cout << "Podaj ilosc studentow : ";

    cin >> n;


    student *tablica = new student[n];



    string dzialanie = "koniec";

    do

    {

		cout <<"\n\nPodaj, co chcesz zrobic (dodaj/kasuj/wyswietl/koniec) : ";

		cin >> dzialanie;

		if (dzialanie != "koniec" && dzialanie != "dodaj" && dzialanie != "kasuj" && dzialanie != "wyswietl")

			dzialanie = "koniec";


		if (dzialanie == "dodaj")

			dodaj();

		if (dzialanie == "kasuj")

			kasuj();

		if (dzialanie == "wyswietl")

			wyswietl();


	}while (dzialanie != "koniec");


    cout <<"\n\n\n";

    system("PAUSE");

    return EXIT_SUCCESS;

}


void dodaj()

{

	cout << "\n\nPodaj numer studenta, ktorego dane chcesz edytowac : ";

    int numer;

    cin >> numer;


    cout << "\n\nPodaj kolejno : imie, nazwisko, srednia ocen, stypendium, wiek\n";

    cin >> tablica[numer].imie;

    cin >> tablica[numer].nazwisko;

    cin >> tablica[numer].srednia_ocen;

    cin >> tablica[numer].stypendium;

    cin >> tablica[numer].wiek;

}


void kasuj()

{

	cout << "\n\nPodaj numer studenta, ktorego dane chcesz skasowac : ";

    int numer;

    cin >> numer;

    tablica[numer].imie =' ';

    tablica[numer].nazwisko = ' ';

    tablica[numer].srednia_ocen = 0;

    tablica[numer].stypendium = 0;

    tablica[numer].wiek = 0;

}


void wyswietl()

{

	cout <<"\n\nWyswietlanie zawartosci tablicy dynamicznej:";

	for (int i = 0; i < n; i++)

	{

		cout << endl << tablica[i].imie;

		cout << endl << tablica[i].nazwisko;

		cout << endl << tablica[i].srednia_ocen;

		cout << endl << tablica[i].stypendium;

		cout << endl << tablica[i].wiek;

	}


}

Jeśli dobrze zrozumiałem to usiłujesz na nowo napisać std::vector http://www.cplusplus.com/reference/stl/vector/ :smiley:

Kod jest zły pod względem ogólnej sztuki pisania kodu i powszechnych praktyk. Zarzuty:

  1. Używanie zmiennych globalnych w funkcjach

  2. Funkcje robiące za dużo na raz: łączysz IO z tym co funkcaj rzeczwywiśćie powinna robić

3, Funkcja kasuj wcale nie robi tego, czego można by się spodziewać po jej nazwie, jedynie przypisuje mało sensowne wartości studentowi (plus patrz 2.)

  1. W zasadzie ten sam zarzut dla funkcji dodaj, ona jedynie ustawia wartości (plus patrz 2.)

  2. Nie zwalniasz dynamicznie przydzielanej pamięci

  3. Nie sprawdzasz w żaden sposób wpisywanych danych, szczególnie indeksów i rozmiaru tablicy.

Błąd, który powoduje wywrócenie się programu wynika stąd, że masz dwa wskaźniki o nazwie tablica - globalny - z niego korzystają funkcje (co jest w większości przypadków złą praktyką, a ten program jest dobrym przykładem dlaczego), ale nie przypisujesz mu żadnego konkretnego adresu w pamięci oraz wskaźnik lokalny w funkcji main, z którym nie robisz nic poza przypisaniem mu wartości dobrego adresu (w sensie adresu zaalokowanej pamięci).

Tworzysz 2 zmienne “tablica” - globalną w 15 linijce i lokalną w funkcji main w 30. Twoje funkcje będą więc odwoływać się do niezainicjowanego globalnego wskaźnika co spowoduje błąd SIGSEGV i w efekcie crash programu

Wystarczy zamienić:

student *tablica = new student[n];

na

tablica = new student[n];

Ponadto skoro przydzielasz pamięć przy użyciu new[], wypadałoby też ją zwolnić używając delete []

PS Plus oczywiście to wszystko to o czym wspomina nr47 , który mnie uprzedził :smiley:

Dziękuję za pomoc, program już działa po wskazówce Pana barry06. Nie jest on najlepiej napisany, ale gdy znajdę wolny czas to go poprawię, a kod umieszczę w tym temacie.