[C++] jak zapisać dużą listę dynamiczną do pliku?

Bash, C, C++, Java, PHP, Ruby, GTK, Qt i wiele innych - wszystko tutaj.
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

[C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Cześć,

mam problem jak zapisać dużą listę dynamiczną do pliku, żeby łatwo było ją wczytać a potem posortować itp.

Struktura wygląda tak:

Kod: Zaznacz cały

struct ksiazka{
     short int cena;
     string tytul;
     string nazwisko;
     string imie;
     short int ilosc;
     ksiazka *nastepny;
}
Napisałem coś takiego, ale nie działa zbyt dobrze:

Kod: Zaznacz cały

void zapisz(ksiazka *adres){
     ifstream file("baza.txt");
     if(file.good()){
          while(adres!= 0){
                 file << adres->tytul << endl << adres->imie << endl << adres->nazwisko << endl << adres->cena << endl << adres->ilosc << endl;
                 adres = adres->nastepny;
           }
     }
     file.close();
}
Proszę o pomoc!
Ostatnio zmieniony 12 cze 2011, 18:07 przez Enkidu, łącznie zmieniany 1 raz.
bigfun
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 109
Rejestracja: 20 mar 2011, 19:08
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Lokalizacja: Warszawa
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: bigfun »

A nie działa w sensie jakim? wywala błąd, czy nie robi tego co byś chciał? napisz coś więcej.
"Never argue with idiot. He will drag you down to his level and then beat with experience."

Nie udzielam pomocy poza forum.
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Wyskakuj mi błąd:

Kod: Zaznacz cały

error: no match for 'operator<<' in 'file << adres->ksiazka::tytul'
Używam Code::Block.
skoczo
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 176
Rejestracja: 09 kwie 2008, 11:40
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: skoczo »

Kod: Zaznacz cały

#include <iostream>
#include <fstream>

using namespace std;

struct ksiazka{
     short int cena;
     string tytul;
     string nazwisko;
     string imie;
     short int ilosc;
     ksiazka *nastepny;
};

void zapisz(ksiazka *adres){
     ofstream file("baza.txt");
     if(file.good()){
          while(adres!= 0){
                 file << adres->tytul << endl << adres->imie << endl << adres->nazwisko << endl << adres->cena << endl << adres->ilosc << endl;
                 adres = adres->nastepny;
           }
     }
     file.close();
}

int main()
{
	ksiazka k;
	k.cena = 100;
	k.tytul = "tytul";
	k.nazwisko = "nazwisko";
	k.imie = "imie";
	k.ilosc = 1;
	k.nastepny = NULL;
	
	zapisz( &k);
	
	return 0;
}
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Działa :D dzięki wielkie!

Mam jeszcze kilka pytań. Napisałem analogiczną funkcję do wczytywania:

Kod: Zaznacz cały

void wczytaj(ksiazka *&adres){
    ifstream file("baza.txt");
    if(file.good()){
        while(adres != NULL){
            file >> adres->tytul >> adres->imie >> adres->nazwisko >> adres->cena >> adres->ilosc;
            adres = adres->nastepny;
        }
    }
    file.close();
ale inicjalizacja nie działa:

Kod: Zaznacz cały

wczytaj( *k);
ani tak:

Kod: Zaznacz cały

wczytaj( *&k);
ani bez wskaźnika. Gdzie popełniłem błąd.

I jeszcze pytanie - jeśli będę chciał zrobić później sortowanie po każdym z elementów struktury, to czy jest jakiś sposób, żeby zrobić to na stringach, czy lepiej wprowadzić tablice char o wielkości "z zapasem pamięci"?
Awatar użytkownika
karmelek
Przyjaciel
Przyjaciel
Posty: 883
Rejestracja: 10 lut 2007, 17:45
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: karmelek »

I jeszcze pytanie - jeśli będę chciał zrobić później sortowanie po każdym z elementów struktury, to czy jest jakiś sposób, żeby zrobić to na stringach, czy lepiej wprowadzić tablice char o wielkości "z zapasem pamięci"?
Mając do stringów zdefiniowany komparator nie wiem gdzie widzisz problem.
bigfun
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 109
Rejestracja: 20 mar 2011, 19:08
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Lokalizacja: Warszawa
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: bigfun »

Enkidu pisze: Napisałem analogiczną funkcję do wczytywania:

Kod: Zaznacz cały

void wczytaj(ksiazka *adres){
    ifstream file("baza.txt");
    if(file.good()){
        while(adres != NULL){
            file >> adres->tytul >> adres->imie >> adres->nazwisko >> adres->cena >> adres->ilosc;
            adres = adres->nastepny;
        }
    }
    file.close();
ale inicjalizacja nie działa:

Kod: Zaznacz cały

wczytaj( *k);
ani tak:

Kod: Zaznacz cały

wczytaj( *&k);
ani bez wskaźnika. Gdzie popełniłem błąd.
Wystarczy jak przekażesz wskaznik, nie potrzebujesz przekazywać referencji do wskaźnika. Przekazywanie referencji powoduje, ze kiedy przechodzisz po liście zmieniając wartość wskaznika *adres, nadpisujesz wartość oryginalnie przekazanego wskaznika. A więc najlepiej:

Kod: Zaznacz cały

ksiazka *k = new ksiazka;
wczytaj(k);
W funkcji wczytującej musisz jednak alokować pamięć dla kolejnych elementów na liście (Bo rozumiem, że przy wczytywaniu nie wiesz, ile masz ksiazek). Warunek na koniec listy (adress != NULL) jest więc bez sensu.

Kod: Zaznacz cały

void wczytaj(ksiazka *&adres){
    ifstream file("baza.txt");
    if(file.good()){
        while(!file.eof()){
            file >> adres->tytul >> adres->imie >> adres->nazwisko >> adres->cena >> adres->ilosc;
            adres->nastepny = new ksiazka;
            adres = adres->nastepny;
        }
    }
    file.close();
"Never argue with idiot. He will drag you down to his level and then beat with experience."

Nie udzielam pomocy poza forum.
Awatar użytkownika
ilu2112
Sędziwy Jeż
Sędziwy Jeż
Posty: 35
Rejestracja: 28 lut 2009, 20:31
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: GNOME
Architektura: x86
Lokalizacja: Łódź
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: ilu2112 »

Jeżeli chodzi o zapis do pliku tylko po to, żeby potem móc wczytać zapisaną strukturę to czemu nikt jeszcze nie wspomniał o plikach binarnych?
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Łał, niewypowiedziane dzięki! :)

Mam jeszcze pytanie - czy w funkcjach drukuj i wczytaj powinno znajdować się na końcu zamknięcie pliku? A propos sortowania stringów to mimo gotowego komparatora nie wiem jak robić to sortowanie i wyszukiwanie wg alfabetu :/ Ani w skrypcie ani w podręczniku Praata do C++ tego nie znalazłem :/

I już ostatnia prośba, czy moglibyście zerknąć na moją funkcję drukuj i dodaj? Drukuj po wczytaniu ostatniej struktury próbuje dalej wczytywać i wywala błąd.

Kod: Zaznacz cały

void drukuj(ksiazka *adres){
    cout << "Zawartosc listy:" << endl;
    if(!adres) return;
    cout << "Tytul ksiazki: " << adres->tytul << endl << "Nazwisko: " << adres->nazwisko << endl << "Imie: "<< adres->imie << endl << "Cena: "<< adres->rok << endl;
    if(adres!=NULL){
       drukuj(adres->nastepny);
    }
};
a tu jest dodaj:

Kod: Zaznacz cały

void dodaj(ksiazka *adres){
    ksiazka *adres;
    glowa = NULL;
    
    cout << "Podaj tytul ksiazki: ";
    adres = new ksiazka();
    string word;
    cin >> word;
    adres->tytul = word;

    cout << "\nPodaj nazwisko: ";
    cin >> word;
    adres->nazwisko = word;

//itd.

    adres = adres->nastepny;
    }
};
Jeszcze raz proszę o pomoc!
Awatar użytkownika
karmelek
Przyjaciel
Przyjaciel
Posty: 883
Rejestracja: 10 lut 2007, 17:45
Płeć: Mężczyzna
Wersja Ubuntu: 11.04
Środowisko graficzne: GNOME
Architektura: x86
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: karmelek »

Mam jeszcze pytanie - czy w funkcjach drukuj i wczytaj powinno znajdować się na końcu zamknięcie pliku? A propos sortowania stringów to mimo gotowego komparatora nie wiem jak robić to sortowanie i wyszukiwanie wg alfabetu :/ Ani w skrypcie ani w podręczniku Praata do C++ tego nie znalazłem :/
Z czym masz problem? Bierzesz dowolny algorytm sortowania liczbowego jak quicksort, merge, albo głupi insertion i w miejscu porównania wykonujesz operacje komparatorem. Zapewne sprowadzi się to do jednego ifa i wsio...
luzakwielki
Wytworny Kaczor
Wytworny Kaczor
Posty: 264
Rejestracja: 19 lis 2008, 11:42
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: KDE Plasma
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: luzakwielki »

ilu2112 pisze:Jeżeli chodzi o zapis do pliku tylko po to, żeby potem móc wczytać zapisaną strukturę to czemu nikt jeszcze nie wspomniał o plikach binarnych?
Widocznie nikogo nie interesuje to czy się szybko wczyta (binarnie nagłówek w którym zapisane jest ile jest wpisów przeczytać i jeden memcopy i wszystko jest wczytane w pamięci, bez marnowania czasu na analize treści tekstu), ani to, że jeśli już się uparł na tekstowe to tak wczytywać jak teraz sobie może na zaliczeniu w szkole, ale nie w realnym świecie (wystarczy, że będzie miał tytuł ze spacją jak np. Pan Tadeusz, i tytuł książki będzie miał Pan, a Tadeusz, zostanie już wczytany do imienia (nazwisko będzie miało "imie", a prawdziwego nazwiska wcale nie odczyta) - ktoś tu zapomniał, że takie wczytywanie nie wczytuje całej linijki, a do pierwszego białego znaku w tekście).
Awatar użytkownika
ilu2112
Sędziwy Jeż
Sędziwy Jeż
Posty: 35
Rejestracja: 28 lut 2009, 20:31
Płeć: Mężczyzna
Wersja Ubuntu: 12.04
Środowisko graficzne: GNOME
Architektura: x86
Lokalizacja: Łódź
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: ilu2112 »

luzakwielki pisze:
ilu2112 pisze:Jeżeli chodzi o zapis do pliku tylko po to, żeby potem móc wczytać zapisaną strukturę to czemu nikt jeszcze nie wspomniał o plikach binarnych?
Widocznie nikogo nie interesuje to czy się szybko wczyta (binarnie nagłówek w którym zapisane jest ile jest wpisów przeczytać i jeden memcopy i wszystko jest wczytane w pamięci, bez marnowania czasu na analize treści tekstu), ani to, że jeśli już się uparł na tekstowe to tak wczytywać jak teraz sobie może na zaliczeniu w szkole, ale nie w realnym świecie (wystarczy, że będzie miał tytuł ze spacją jak np. Pan Tadeusz, i tytuł książki będzie miał Pan, a Tadeusz, zostanie już wczytany do imienia (nazwisko będzie miało "imie", a prawdziwego nazwiska wcale nie odczyta) - ktoś tu zapomniał, że takie wczytywanie nie wczytuje całej linijki, a do pierwszego białego znaku w tekście).
Dokładnie o tym myślałem, gdy pisałem swoją wiadomość. Enkidu, jeżeli coś robisz nawet na zwykłe zaliczenie w szkole to zrób to dobrze. Być może w przyszłości to wykorzystasz, a na pewno nabyta wiedza Ci się przyda. Rzuć okiem na pliki binarne. Chwila (dosłownie!) lektury pozwoli Ci na szybkie wczytywanie i zapisywanie struktur do pliku. Do tego nie będziesz miał problemów z białymi znakami w nazwach, tytułach itd.
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Hm, nawet nie wiedziałem, że to nie wczyta dłuższego tytułu... :/ Zmieniam to na plik binarny, dzięki za radę!

Jeszcze tylko mam prośbę o przyjrzenie się tym funkcjom na górze oraz wyjaśnienie jak zaimplementować ten komparator!
fraktal
Piegowaty Guziec
Piegowaty Guziec
Posty: 3
Rejestracja: 21 mar 2011, 22:31
Płeć: Mężczyzna
Wersja Ubuntu: 10.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: fraktal »

Jako że to mój pierwszy post, serdecznie witam.

Implementacja komparatora

Dojdziemy do tego metodą prób i błędów.
Piszemy programik:

Kod: Zaznacz cały

#include <iostream>
#include <string>

using namespace std;

int main()
{
    string s1, s2, s3, s4;
    s1 = "a";
    s2 = "A";
    s3 = "ab";
    s4 = "ba";
    cout << (s1 < s2) << endl;
    cout << (s2 < s1) << endl;
    cout << (s3 < s4) << endl;
}
Wynikiem jest:

Kod: Zaznacz cały

0
1
1
Dochodzimy do następujących wniosków:
  • Litery większe są mniejsze niż małe (czyli trochę inaczej niż by wskazywała intuicja)
    porównywanie "idzie" od lewej do prawej w danym słowie.
Inne przypadki możesz sobie sam sprawdzić, o ile uważasz to za niezbędne.

Widać więc, że porównywanie działa analogicznie jak dla liczb. Wystarczy więc, że w swojej wersji sortowania zamiast porównywania liczb wstawisz analogiczne porównywanie stringów i powinno wszystko hulać.
luzakwielki
Wytworny Kaczor
Wytworny Kaczor
Posty: 264
Rejestracja: 19 lis 2008, 11:42
Płeć: Mężczyzna
Wersja Ubuntu: inny OS
Środowisko graficzne: KDE Plasma
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: luzakwielki »

fraktal pisze:Dojdziemy do tego metodą prób i błędów.
Ty serio metodą prób i błędów dochodziłeś do tego czy się zgrywasz? To chyba jasne, że małe litery są większe od dużych i wynika to z przyporządkowania znaków liczbą w ASCII (np. 'a' to 97, a 'A' to 65), jednak takie porównywanie można zastosować tylko jak się jest anglikiem, nie uznającym innych języków za dopuszczalne - np. polska litera 'ą' w kodowaniu ISO ma numer 177, a w Unicode 261, więc przy takim sortowaniu jak proponujesz będziesz miał 'ą' jako późniejszą w alfabecie niż 'z'.
fraktal
Piegowaty Guziec
Piegowaty Guziec
Posty: 3
Rejestracja: 21 mar 2011, 22:31
Płeć: Mężczyzna
Wersja Ubuntu: 10.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: fraktal »

Pewnie że żartowałem:)
Chciałem tylko pokazać, że nawet jak się nie ma odpowiednio dużej wiedzy, to można do pewnych rzeczy dojść właśnie poprzez próby, niekoniecznie czytając całą dokumentację. A że pomaga to w kreatywnym myśleniu to chyba tylko lepiej, prawda?

PS. Nie odrzucam w tym momencie gruntownej wiedzy na dany temat, taka też powinna być zdobywana.
Awatar użytkownika
Enkidu
Serdeczny Borsuk
Serdeczny Borsuk
Posty: 139
Rejestracja: 10 wrz 2008, 12:10
Płeć: Mężczyzna
Wersja Ubuntu: 13.04
Środowisko graficzne: Unity
Architektura: x86_64

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: Enkidu »

Dzięki za wyjaśnienie o co chodzi z komparatorem ;)

Ostatnia prośba... Czy w tej funkcji jest błąd?

Kod: Zaznacz cały

void wczytaj(zawodnik *adres){
    ifstream file("baza.txt");
    if(file.good()){
          while(!file.eof()){
              file >> adres->imie >> adres->nazwisko >> adres->ranking;
              adres->nastepny = new zawodnik;
              adres = adres->nastepny;
              adres->nastepny = NULL;
          }
    }
    file.close();
}
Bo jak potem drukuje to, to drukuje mi dwa puste kolejne elementy :/
fraktal
Piegowaty Guziec
Piegowaty Guziec
Posty: 3
Rejestracja: 21 mar 2011, 22:31
Płeć: Mężczyzna
Wersja Ubuntu: 10.04
Środowisko graficzne: GNOME
Architektura: x86_64
Kontakt:

Re: [C++] jak zapisać dużą listę dynamiczną do pliku?

Post autor: fraktal »

To tworzenie elementu na samym końcu nie jest najrozsądniejszym wyjściem... Jak się znajdzie przed EOF-em znak biały to wczytajka wejdzie do pętli i utworzy pusty obiekt (mimo że nie powinna).

Spróbuj postąpić wg poniższego schematu, jak dla siebie coś pisałem to działało:
  • (to już w pętli po sprawdzeniu czy można wykonywać operacje na strumieniu)
    Utwórz obiekt
    Wczytaj dane
    Dołącz do listy
W ten sposób, gdy wczytasz ostatni element, nie utworzysz zbędnego elementu pustego.

Warto by też pomyśleć nad stworzeniem listy - klasy, stanowi to dobry trening programowania i jest dużo wygodniejsza w obsłudze (o ile się czujesz na siłach :)).
ODPOWIEDZ

Wróć do „Programowanie”

Kto jest online

Użytkownicy przeglądający to forum: Google [Bot] i 2 gości