[C++] Funkcja cin.ignore() nie działa poprawnie


(eureka 170) #1

Witam, chciałem napisać program, który będzie bazą studentów i pracowników danego wydziału. Jestem w trakcie pisania i niestety mam problem z funkcjami cin.ignore() i cin.getline(). Oto kod:

projekt.h

#ifndef PROJEKT_H_INCLUDED

#define PROJEKT_H_INCLUDED

class Kurs

{

    private:

    char *kod;

    char *nazwa;

    char *temp;

    public:

    Kurs();

    ~Kurs();

    void Pobierz_Nazwe();

    void Pobierz_Kod();

};


class Osoba

{

    protected:

    char *imie;

    char *nazwisko;

    char *adres_zamieszkania;

    char *email;

    char *telefon;

    char *pesel;

    char *data_ur;

    char *plec;

    char *temp;


    public:

    Osoba();

    ~Osoba();

    void Pobierz_Imie();

    void Pobierz_Nazwisko();

    void Pobierz_Adres();

    void Pobierz_Email();

    void Numer_Telefonu();

    void Pobierz_Pesel();

    void Data_Urodzenia();

    void Pobierz_Plec();

};


class Student: public Osoba

{

    protected:

    char *numer_indeksu;

    char *kierunek;

    int rok;

    Kurs *wsk;


    public:

    Student();

    ~Student();

    void Pobierz_Numer();

    void Pobierz_Kierunek();

    void Pobierz_Kurs();

    int Pobierz_Rok();

};

class Pracownik: public Osoba

{

    protected:

    char *stanowisko;

    int staz;

    char *umowa;

    Kurs *wsk;


    public:

    Pracownik();

    ~Pracownik();

    void Pobierz_Stanowisko();

    int Pobierz_Staz();

    void Pobierz_Umowe();

    void Pobierz_Kurs();

};


#endif // PROJEKT_H_INCLUDED

projekt.cpp

#include 

#include "projekt.h"

#include 

using namespace std;

Kurs::Kurs()

{

    Pobierz_Nazwe();

    Pobierz_Kod();

}

Kurs::~Kurs()

{

    delete nazwa;

    delete kod;

}

void Kurs::Pobierz_Nazwe()

{

    temp = new char[100];

    cout << "Podaj nazwe kursu: ";

    cin.ignore();

    cin.getline(temp,100);

    nazwa = new char[strlen(temp)];

    strcpy(nazwa,temp);

    delete temp;

}

void Kurs::Pobierz_Kod()

{

    temp = new char[100];

    cout << "Podaj kod kursu: ";

    cin.ignore();

    cin.getline(temp,100);

    kod = new char[strlen(temp)];

    strcpy(kod,temp);

    delete temp;

}

Osoba::Osoba()

{

    Pobierz_Imie();

    Pobierz_Nazwisko();

    Pobierz_Plec();

    Data_Urodzenia();

    Pobierz_Adres();

    Pobierz_Email();

    Pobierz_Pesel();

    Numer_Telefonu();

}

Osoba::~Osoba()

{

    delete imie;

    delete nazwisko;

    delete adres_zamieszkania;

    delete email;

    delete telefon;

    delete pesel;

    delete data_ur;

    delete plec;

}

void Osoba::Pobierz_Imie()

{

    temp = new char[100];

    cout << "Podaj imie: ";

    cin.ignore();

    cin.getline(temp,100);

    imie = new char[strlen(temp)];

    strcpy(imie,temp);

    delete temp;

}

void Osoba::Pobierz_Nazwisko()

{

    temp = new char[100];

    cout << "Podaj nazwisko: ";

    cin.ignore();

    cin.getline(temp,100);

    nazwisko = new char[strlen(temp)];

    strcpy(nazwisko,temp);

    delete temp;

}

void Osoba::Pobierz_Adres()

{

    temp = new char[100];

    cout << "Podaj adres zamieszkania: ";

    cin.ignore();

    cin.getline(temp,100);

    adres_zamieszkania = new char[strlen(temp)];

    strcpy(adres_zamieszkania,temp);

    delete temp;

}

void Osoba::Pobierz_Email()

{

    temp = new char[100];

    cout << "Podaj email: ";

    cin.ignore();

    cin.getline(temp,100);

    email = new char[strlen(temp)];

    strcpy(email,temp);

    delete temp;

}

void Osoba::Numer_Telefonu()

{

    temp = new char[20];

    cout << "Podaj numer telefonu: ";

    cin.ignore();

    cin.getline(temp,20);

    telefon = new char[strlen(temp)];

    strcpy(telefon,temp);

    delete temp;

}

void Osoba::Pobierz_Pesel()

{

    temp = new char[100];

    cout << "Podaj PESEL: ";

    cin.ignore();

    cin.getline(temp,100);

    pesel = new char[strlen(temp)];

    strcpy(pesel,temp);

    delete temp;

}

void Osoba::Data_Urodzenia()

{

    temp = new char[100];

    cout << "Podaj date urodzenia: ";

    cin.ignore();

    cin.getline(temp,100);

    data_ur = new char[strlen(temp)];

    strcpy(data_ur,temp);

    delete temp;

}

void Osoba::Pobierz_Plec()

{

    temp = new char[100];

    cout << "Podaj plec: ";

    cin.ignore();

    cin.getline(temp,100);

    plec = new char[strlen(temp)];

    strcpy(plec,temp);

    delete temp;

}

Student::Student()

{

    Pobierz_Numer();

    Pobierz_Kierunek();

    Pobierz_Rok();

    Pobierz_Kurs();

}

Student::~Student()

{

    delete numer_indeksu;

    delete kierunek;

    delete wsk;

}

void Student::Pobierz_Numer()

{

    temp = new char[100];

    cout << "Podaj numer indeksu: ";

    cin.ignore();

    cin.getline(temp,100);

    numer_indeksu = new char[strlen(temp)];

    strcpy(numer_indeksu,temp);

    delete temp;

}

void Student::Pobierz_Kierunek()

{

    temp = new char[100];

    cout << "Podaj kierunek studiow: ";

    cin.ignore();

    cin.getline(temp,100);

    kierunek = new char[strlen(temp)];

    strcpy(kierunek,temp);

    delete temp;

}

int Student::Pobierz_Rok()

{

    cout << "Podaj rok nauki studenta: ";

    cin >> rok;

    return rok;

}

void Student::Pobierz_Kurs()

{

    wsk = new Kurs;

}

Pracownik::Pracownik()

{

    Pobierz_Stanowisko();

    Pobierz_Staz();

    Pobierz_Umowe();

}

Pracownik::~Pracownik()

{

    delete stanowisko;

    delete umowa;

}

void Pracownik::Pobierz_Stanowisko()

{

    temp = new char[100];

    cout << "Podaj stanowisko pracownika: ";

    cin.ignore();

    cin.getline(temp,100);

    stanowisko = new char[strlen(temp)];

    strcpy(stanowisko,temp);

    delete temp;

};

int Pracownik::Pobierz_Staz()

{

    cout << "Jaki jest staz tego pracownika(w latach): ";

    cin >> staz;

    return staz;

};

void Pracownik::Pobierz_Umowe()

{

    temp = new char[100];

    cout << "Podaj stanowisko pracownika: ";

    cin.ignore();

    cin.getline(temp,100);

    umowa = new char[strlen(temp)];

    strcpy(umowa,temp);

    delete temp;

};

main.cpp

#include 

#include "projekt.h"

using namespace std;


int main()

{

    Student A;

    return 0;

}

Problem pojawia się w momencie, gdy chcę wpisać nazwę kursu. Wtedy program nie pozwala mi wpisać tej nazwy, a ja nie wiem jak poprawić kod, by móc to zrobić. Co tu jest nie tak?


([alex]) #2

Pomyliłeś:

cin.ignore();

z:

cin.sync();

Normalnie zastąp ignore na sync w całym pliku.

Tak a propos straszne rzeczy wyprawiasz:

    char temp[100]; //temp = new char[100];cout  "Podaj nazwe kursu: ";cin.sync(); //cin.ignore();cin.getline(temp,100);nazwa) delete[] nazwa; // koniecznie inaczej zapchasz pamięćnazwa=strdup(temp);//nazwa = new char[strlen(temp)];

(eureka 170) #3

Właśnie poprawiłem, jak radziłeś i nie pomogło. Efekt jest taki sam :frowning:


([alex]) #4

Poprawiłem post wyżej, poczytaj. Masz bałagan w kodzie, mażesz po pamięci.


(eureka 170) #5

Hm... być może faktycznie muszę zmienić metody klasy, jednak zanim będę to robił, to staram się dociec, dlaczego nie mogę wpisać nazwy kursu przy takiej strukturze programu.

Skopiowałem Twój kod do metody Pobierz_Nazwe:

char temp[100]; //temp = new char[100];

    cout << "Podaj nazwe kursu: ";

    cin.sync(); //cin.ignore();

    cin.getline(temp,100);

    if(nazwa) delete[] nazwa; // koniecznie inaczej zapchasz pamięć

    nazwa=strdup(temp);

    //nazwa = new char[strlen(temp)];

    //strcpy(nazwa,temp); // kopiujesz jeden bajt więcej niż przydzieliłeś

    //delete temp;

i efekt się nie zmienił :(, tylko nie wiem dlaczego nic się nie zmienia :frowning:

Jeszcze mam pytania, dlaczego wg Ciebie lepiej jest utworzyć statyczną tablicę temp? Jeżeli utworzę 20 kursów to będzie 20 takich obiektów, nie lepiej utworzyć temp, ale dynamicznie? I drugie pytanie, co dałaby ta komenda: if(nazwa) delete[] nazwa;?


([alex]) #6

Effekt ten sam prawdopodobnie dla tego że zamieniłeś ignore na sync oraz naprawiłeś "mazanie po pamięci" tylko w jednej metodzie, w pozostałych masz nadal to samo a metody te wywołują się po kolei w konstruktorze (czarki przechodzą na widok takiego rozwiązania).

Ten temp jest wewnątrz metody, po jej zakończeniu znika.

if(nazwa) delete[] nazwa; // Zanim przypiszesz do nazwy inny wskaźnik, musisz zwolnić to co było w nim przed tym (jeżeli było)


(Monczkin) #7

eureka 170 , nazwij proszę temat konkretnie, bez zbędnych problemów w tytule. Inaczej wyciągnę konsekwencje. Przeczytaj ten temat. http://forum.dobreprogramy.pl/viewtopic.php?f=16&t=394978


(eureka 170) #8

Witam, teraz po rozbudowaniu pliku main.cpp mam problem z funkcją switch.

#include 

#include "projekt.h"

using namespace std;


int main()

{

    Lista_Studentow *A;

    Pracownik *prac;

    Kurs *kr;

    int odp1, odp2, odp3;

    while(odp1!=4)

    {

        cout << " ********MENU**********" << endl;

        cout << "(1) Studenci (2) Pracownicy (3) Kursy (4) Zakoncz" << endl;

        cin >> odp1;

        switch(odp1)

        {

            case 1:

            while(odp2!=3)

            {

                cout << "(1) Zaoczni (2) Dzienni (3) Zakoncz" << endl;

                cin >> odp2;

                switch(odp2)

                {

                        case 1:

                        A = new Lista_Zaocznych;

                        while(odp3!=5)

                        {

                            cout << "(1)Dodaj studenta (2) Usun wybranego studenta (3) Wyswietl" << endl;

                            cout << "(4) Usun wszystkich studentow (5) Zakoncz" << endl;

                            cin >> odp3;

                            switch(odp3)

                            {

                                case 1:

                                A->Dodaj();

                                break;

                                case 2:

                                A->UsunWybranegoStudenta();

                                break;

                                case 3:

                                A->wyswietl();

                                break;

                                case 4:

                                A->UsunWszystkieElementy();

                                break;

                            }

                        }

                        break;

                        case 2:

                        A = new Lista_Dziennych;

                        while(odp3!=5)

                        {

                            cout << "(1)Dodaj studenta (2) Usun wybranego studenta (3) Wyswietl" << endl;

                            cout << "(4) Usun wszystkich studentow (5) Zakoncz" << endl;

                            cin >> odp3;

                            switch(odp3)

                            {

                                case 1:

                                A->Dodaj();

                                break;

                                case 2:

                                A->UsunWybranegoStudenta();

                                break;

                                case 3:

                                A->wyswietl();

                                break;

                                case 4:

                                A->UsunWszystkieElementy();

                                break;

                            }

                        }

                        break;

                        default:

                        cout << "Podaj jeszcze raz liczbe" << endl;

                        break;

                    }

            }

            break;

        }

    }


    return 0;

}

Przykładowo wybieram "Studenci", potem "Zaoczni", a potem wybiorę "Zakoncz". Wtedy program przekieruje mnie do menu gdzie mogę wybrać albo studentów zaocznych albo dziennych. Ale teraz jak próbuję wybrać dziennych bądź zaocznych to program nadal pokazuje mi wybór studenta zaocznego bądź dziennego zamiast pokazywać mi menu konkretnego studenta. Co jest tu nie tak?