Strona 1 z 1
[C++] jak zapisać dużą listę dynamiczną do pliku?
: 12 cze 2011, 16:28
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!
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 12 cze 2011, 17:40
autor: bigfun
A nie działa w sensie jakim? wywala błąd, czy nie robi tego co byś chciał? napisz coś więcej.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 12 cze 2011, 18:02
autor: Enkidu
Wyskakuj mi błąd:
Kod: Zaznacz cały
error: no match for 'operator<<' in 'file << adres->ksiazka::tytul'
Używam Code::Block.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 12 cze 2011, 18:58
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;
}
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 12 cze 2011, 21:35
autor: Enkidu
Działa

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:
ani tak:
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"?
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 13 cze 2011, 01:04
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.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 13 cze 2011, 01:48
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:
ani tak:
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:
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();
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 13 cze 2011, 10:52
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?
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 16 cze 2011, 00:15
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!
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 16 cze 2011, 00:50
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...
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 16 cze 2011, 02:06
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).
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 16 cze 2011, 09:41
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.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 16 cze 2011, 19:31
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!
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 19 cze 2011, 10:51
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:
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ć.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 19 cze 2011, 12:09
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'.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 19 cze 2011, 12:27
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.
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 20 cze 2011, 00:43
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 :/
Re: [C++] jak zapisać dużą listę dynamiczną do pliku?
: 20 cze 2011, 14:48
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

).