Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Programowanie obiektowe - problem z dynamiczną tablicą stringów w klasie

Ostatnio zmodyfikowano 2013-03-04 23:02
Autor Wiadomość
karpiq
Temat założony przez niniejszego użytkownika
Programowanie obiektowe - problem z dynamiczną tablicą stringów w klasie
» 2013-03-04 11:58:57
Witam!
Program crashuje przy wpisywaniu danych do tablicy stringów (Przedmioty).


C/C++
#include <iostream>
#include <string>
using namespace std;


class Student
{
public:
   
    string Imie;
    string Nazwisko;
    int Nr_albumu;
    float Srednia;
    string * Przedmioty;
    Student() { }
    Student( int n );
   
};


Student::Student( int n )
{
    Przedmioty = new string[ n ];
}

int main()
{
    int j, i, n;
    int K;
   
    cout << "Podaj liczbe studentow: ";
    cin >> K;
    Student * tablica = new Student[ K ];
    for( i = 0; i < K; i++ )
    {
        cout << endl << "Student nr. " << i + 1 << endl << "Imie: ";
        cin >> tablica[ i ].Imie;
        cout << "Nazwisko: ";
        cin >> tablica[ i ].Nazwisko;
        cout << "Nr. albumu: ";
        cin >> tablica[ i ].Nr_albumu;
        cout << "Srednia: ";
        cin >> tablica[ i ].Srednia;
        cout << "Ilosc przedmiotow: ";
        cin >> n;
       
        for( j = 0; j < n; j++ )
        {
            cout << "Przedmiot nr. " << j + 1 << ": ";
            cin >> tablica[ i ].Przedmioty[ j ];
        }
    }
   
    return 0;
}

Jak to zrobić, żeby działało?
P-77644
unimator
» 2013-03-04 13:57:02
C/C++
// 1.
Student() { } // <--- (*)
Student( int n );

//...

// 2.
Student::Student( int n )
{
    Przedmioty = new string[ n ];
}

//...

// 3.
Student * tablica = new Student[ K ];

//...

// 4.
for( j = 0; j < n; j++ )
{
    cout << "Przedmiot nr. " << j + 1 << ": ";
    cin >> tablica[ i ].Przedmioty[ j ];
}
Punkt 3.
new Student [K] spowoduje wywołanie konstruktora Student() (punkt 1., (*)), który nic nie robi. Konstruktor Student (int) (punkt 2.) nie zostanie wywołany a jest to jedyny konstruktor, który alokuje pamięć dla zmiennej Przedmioty. Tym samym w punkcie 4. odwołujesz się do niezaalokowanej pamięci.
Dla zasady jeszcze przypomnę, że zaalokowaną dynamicznie pamięć należy zwolnić.
P-77646
karpiq
Temat założony przez niniejszego użytkownika
» 2013-03-04 14:01:58
Jak wybrać odpowiedni konstruktor, albo zrobić ten alokujący pamięć domyślnym?

Po pozbyciu się : Student() { } wyskakuje: "error C2512: 'Student' : no appropriate default constructor available"
P-77647
unimator
» 2013-03-04 14:07:16
:D Jak coś Ci nie działa to nie oznacza, że trzeba to zaraz usunąć. Wystarczy zamienić tą linijkę:
C/C++
Student * tablica = new Student[ K ];
na tą:
C/C++
Student * tablica = new Student( rozmiar_tablicy )[ K ];
Chociaż jeśli nie zamierzasz użyć żadnych metod, które ustalą wielkość tablicy, na którą będzie wskazywać wskaźnik Przedmioty, to możesz usunąć ten bezparametrowy konstruktor bo jak sam widzisz tylko Ci błędów narobił.
P-77648
karpiq
Temat założony przez niniejszego użytkownika
» 2013-03-04 14:11:13
Hm, to dalej nie rozwiązuje problemu.
Wielkość tablicy przedmiotów jest wczytywana później i dla każdego studenta może być inna liczba przedmiotów. Da się zrobić, żeby dopiero od tego momentu (po wczytaniu n) korzystał z tego konstruktora?

A może jest jakieś inne rozwiązanie którego nie widzę?
P-77649
unimator
» 2013-03-04 14:24:42
Aha, sorry nie analizowałem do końca programu.
Alokacje pamięci musisz więc zrobić po linijce:
C/C++
cout << "Ilosc przedmiotow: ";
cin >> n;
Najprościej stworzyć jakąś metodę, która się tym zajmie, np.
C/C++
class Student
{
public:
   
    string Imie;
    string Nazwisko;
    int Nr_albumu;
    float Srednia;
    string * Przedmioty;
    Student() { }
    Student( int n );
    Alokacja( int n )
    {
        Przedmioty = new string[ n ];
    }
};

//...

cout << "Ilosc przedmiotow: ";
cin >> n;
tablica[ i ].Alokacja( n ); // <---

// Równie dobrze możesz zapisać jednak w ten sposób:
// tablica.Przedmioty = new string [n];
// Jednak poczytaj sobie o enkapsulacji/hermetyzacji w programowaniu obiektowym.

Przy okazji, to ten konstruktor, który podałem w poprzednim poście nie zadziała (bo właśnie to sprawdziłem). Spróbuje ogarnąć jak to poprawnie zapisać.
P-77650
karpiq
Temat założony przez niniejszego użytkownika
» 2013-03-04 14:37:10
Użyłem tablica[.i].Przedmioty = new string [n]; i, wydaje się, że działa. ;)
Mam jeszcze jedno małe pytanie:
Jak w osobnej funkcji zwiększyć tablicę(pamięć jaką ma przypisaną) aby dodać kolejnego studenta?[/i]
P-77651
unimator
» 2013-03-04 14:44:08
Musisz stworzyć tablicę o rozmiarze n+1 (gdzie n to obecny rozmiar tablicy), przekopiować starą tablicę do nowej i na jej koniec wrzucić tego studenta, którego dodajesz (kolejność możesz zamienić oczywiście). Nie da się jednak od tak zwiększyć tablicy już istniejącej.

Do takich zabiegów (dodawanie, usuwanie elementów) służą listy. Nie są one częścią C++ ale można je samemu zaimplementować (bodajże klasa std::vector działa na zasadzie takich list albo udostępnia taki mechanizm).
P-77652
« 1 » 2 3
  Strona 1 z 3 Następna strona