• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Zapisanie danych do pliku .txt przy użyciu wskaźników

0 głosów
728 wizyt
pytanie zadane 2 października 2018 w C i C++ przez Kontrane Początkujący (260 p.)

Witam serdecznie wszystkich!

Proszę o pomoc w rozwiązaniu problemu :) Tworzę obiektowo e-dziennik w C++, którego jedną z funkcjonalności jest zapis utworzonej dynamicznie w programie listy uczniów (numerek, imię, nazwisko) do pliku .txt, aby później móc wczytać taką listę, taki dziennik, przy następnym uruchomieniu. 

Obecnie utknąłem w momencie zapisu listy do pliku .txt. Dodam, że w całym programie (piszę go w strukturze pliku projektowego - podział na 3 pliki) raczej nie mam problemu z operowaniem na utworzonej dynamicznie liście uczniów (lista jednokierunkowa). Oto ciało mojej metody:

void Lista::zapisz_dziennik()
{
    Uczen* temp=pierwszy;
    if(temp)
    {
        char nazwa[2];
        cout<<"Podaj nazwę klasy (np. 1B): ";
        cin>>nazwa;
        fstream plik;
        plik.open(nazwa, ios::out);
        while(temp->nastepny)
        {
            plik<<temp->nr<<" "<<temp->imie<<" "<<temp->nazwisko<<endl;
            temp=temp->nastepny;
        }
        plik<<temp->nr<<" "<<temp->imie<<" "<<temp->nazwisko;

        cout<<"Zapisuje dziennik klasy "<<nazwa;
        Sleep(250);
        cout<<".";
        Sleep(250);
        cout<<".";
        Sleep(250);
        cout<<".";
        Sleep(250); //animacja
        plik.close();
    }
    else
    {
        cerr<<"\aBłąd. Dziennik jest pusty!";
        Sleep(2000);
    }
}

Problem pojawia się jedynie przy zapisie danych do pliku .txt (analogiczny cout<<temp->nr<<" "... itd. działa bez problemu - napisałem nawet specjalną metodę bardzo zbliżoną do tej, do wyświetlania całej listy na oknie konsoli).

Przy wpisaniu chociaż jednego ucznia, zamiast zapisu w notatniku w stylu:

1 Jan Kowalski

otrzymuję

33556432 (adres w pamięci RAM?)

Pozdrawiam wszystkich serdecznie i liczę na pomoc :)

PS Od razu dodam, dołączyłem bibliotekę <fstream>!

komentarz 2 października 2018 przez niezalogowany
A jak wstawisz na stale nazwe pliku to tez nie dziala ?

1 odpowiedź

0 głosów
odpowiedź 3 października 2018 przez draghan VIP (106,230 p.)

Samo zapisywanie wygląda w porządku. Za to gorzej z otwieraniem pliku.

1. Masz za mały bufor na nazwę - zapomniałeś, że C-stringi są zakończone znakiem terminującym '\0'. Jeśli nazwa pliku ma być dwuznakowa - potrzebujesz trzy miejsca w buforze. A w ogóle lepiej użyć std::string i nie zaprzątać sobie tym głowy.

2. Nie sprawdzasz, czy plik poprawnie się otworzył.

std::string nazwa;
cout<<"Podaj nazwę klasy (np. 1B): ";
cin>>nazwa;
ofstream plik(nazwa); // obiekt ofstream (output-file-stream) domyslnie otwiera sie w trybie do zapisu
if(!plik.good())
{
    std::cerr << "Nie udalo sie otworzyc pliku!";
    return;
}

 

komentarz 10 października 2018 przez Kontrane Początkujący (260 p.)
Pięknie dziekuję! Oczywiście problemem był za mały rozmiar tablicy char na nazwę klasy, po zmianie z [2] na [3] wszystko działa (tak to jest, jak całe życie używa się stringa). A stringa niestety nie można użyc, ponieważ metoda open za argument bierze chara,  a nie stringa :(

Pozdrawiam!
komentarz 10 października 2018 przez draghan VIP (106,230 p.)

metoda open za argument bierze chara,  a nie stringa :(

Od C++11 wzwyż jest dostępne przeciążenie metody open dla ścieżki podanej jako std::string [patrz (3)]. Tak samo z konstruktorem.

W ogóle nie potrzebujesz używać metod open i close - jeśli podasz ścieżkę do pliku w konstruktorze, strumień do tego pliku się otworzy i nie będzie potrzeby wołania open. Zaś zamykanie strumienia odbywa się automatycznie w destruktorze, więc nie ma też potrzeby wołania close. Chyba, że chcesz użyć danej zmiennej ponownie (a Ty nie używasz). Czy to nie ładniejsze? :)

if(temp)
{
    std::string nazwa;
    cout<<"Podaj nazwę klasy (np. 1B): ";
    cin>>nazwa;
    ofstream plik(nazwa); // obiekt ofstream (output-file-stream) domyslnie otwiera sie w trybie do zapisu
    if(!plik.good())
    {
        std::cerr << "Nie udalo sie otworzyc pliku!";
        return;
    }

    while(temp->nastepny)
    {
        plik<<temp->nr<<" "<<temp->imie<<" "<<temp->nazwisko<<endl;
        temp=temp->nastepny;
    }
    plik<<temp->nr<<" "<<temp->imie<<" "<<temp->nazwisko;

    cout<<"Zapisuje dziennik klasy "<<nazwa;
    Sleep(250); // Sleep jest nieprzenośny, dobrze byłoby tego unikać
    cout<<".";
    Sleep(250);
    cout<<".";
    Sleep(250);
    cout<<".";
    Sleep(250); //animacja
} // wraz z opuszczeniem tego zakresu, zmienna 'plik' jest usuwana, przy czym 
  // wywoływany jest jej destruktor, co automatycznie zamyka strumień

Pozdrawiam!

Pozdrawiam również. :)

Podobne pytania

+3 głosów
4 odpowiedzi 2,441 wizyt
pytanie zadane 30 czerwca 2015 w C i C++ przez Phobos Użytkownik (720 p.)
+1 głos
0 odpowiedzi 192 wizyt
pytanie zadane 12 czerwca 2020 w C i C++ przez amtrax Dyskutant (9,630 p.)
0 głosów
2 odpowiedzi 658 wizyt
pytanie zadane 14 lipca 2020 w C i C++ przez Kxmil Nowicjusz (220 p.)

93,428 zapytań

142,423 odpowiedzi

322,652 komentarzy

62,789 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

VMware Cloud PRO - przenieś swoją infrastrukturę IT do chmury
...