|
[+]tablice dynamiczne c++
skotik87 - 10-01-2008 16:21
Witam, mam problem z tablicami dynamicznymi. Ciag dalszy mojego programu i teraz go musze przerabiac. chce zrobic cos takiego: wczytuje kilka razy dane i chce zeby byly zapamietywane w pamieci (rozszerzenie tablicy dynamicznej) . i tu jest problem nie wiem jak to zrobic zeby to dzialalo. Potrzebne mi to bo chce pozniej dorobic funkcje zebym mogl kiedy chce wybrac opcje zapis i wtedy wszystko co jest w tablicy zapisuje do pliku.
Mniej wiecej tego typu funcja ktora mi wczytuje dane Probowalem to zrobic z jakas pomocnicza tablica ale nie wyszlo mi to. Teraz czytam o realloc, moze cos z tego wyjdzie :/
Za wszelkie podpowiedzi dzieki. Pozdrawiam skotik87
mlyczek - 10-01-2008 16:36
Jedno pytanie: czy chcesz tworzyć dynamicznie za każdym razem nową tablicę i do niej wczytywać dane, czy masz jedną globalną i chcesz tylko zwiększyć jej rozmiar i w nowe miejsce wczytać dane? Bo do tego pierwszego realloc Ci się nie przyda (a tak zrozumiałem to co napisałeś).
skotik87 - 10-01-2008 16:57
Najlepiej chyba by bylo zwiekszac jej rozmiar, zreszta mysle ze kazde rozwiazanie bedzie dobre bo mnie zaczyna czas gonic. Wytlumacze na przykladzie o co mi dokladnie chodzi. Zalozmy ze wczytalem dane osoby, pozniej wpisalem dane dwoch osob i stwierdzilem ze sobie teraz to wszystko zapisze do pliku. naciskam klawisz ktory odpowiada za funkcje zapisu i zapisuje. Wczesniej mialem zeby odrazu zapisywalo dane do pliku, ale kolesiowi na uczelni to nie pasuje :/
mlyczek - 10-01-2008 17:16
tylko, że funkcja, którą podałeś w pierwszym poście nie zmieni Ci rozmiaru tablicy, bo tworzy nową. Nie wiem, co poza opisanymi rzeczami (czytanie danych i pisanie do plików) ma ten program jeszcze robić, ale jeśli to nie przeszkodzi, to wygodniej i łatwiej byłoby zrobić po prostu listę jedno- (lub w razie potrzeby dwu-) stronną. Dane (imię, nazwisko, itd.) trzymać w jakiejś strukturze i tylko tworzyć nową strukturę, wczytywać do niej dane i zapisywać wskaźnik na nową strukturę w ostatniej z listy.
Można też zrobić globalną tablicę i zmieniać jej rozmiar realloc'em, ale wtedy w/w funkcja musiałaby przyjmować jako parametr wskaźnik na ta tablicę (chyba, że funkcja jest definiowana w tym samym module co deklarowana tablica). Musiałbyś też gdzieś trzymać rozmiar tablicy i najprawdopodobniej też przekazywać go do funkcji.
Jeśli wykładowca/ćwiczeniowiec nie zabronił, to możesz też użyć vector'a z STL'a, on sam się rozszerza, Ty tylko dodajesz elementy <- to jest najprostsze w implementacji.
skotik87 - 10-01-2008 18:02
sprobuje pokombinowac cos z dodatkowa tablica, ewentualnie poszukam cos konkretnego o vectorze. o listach nie mam zielonego pojecia wiec nie probuje bo szkoda mi czasu. moze cos zrobie sensownego
grzesiek - 10-01-2008 18:22
w STL są klasy tablic dowolnego typu oparte na template i z przeciążonym operatorem indeksowania[] ;-) .... tablice zwiększają się automatycznie co 10 elementów jak dobrze pamiętam - to takie gotowe rozwiązanie a jak byś chciał sam się w to bawić to albo trzeba zrobić jakąś strukturę albo do tablicy wskaźników dodawać wskaźniki z dynamicznie zaalokowaną strukturą, polecam przestudiowanie źródeł GLib i klasę/strukturę GArray :-)
skotik87 - 10-01-2008 18:36
mi trzeba latwe i szybkie rozwiazanie tego problemu ;p nie mam tyle czasu zeby kombinowac az tak bardzo z nowymi bibliotekami.
salmon - 10-01-2008 18:39
mi trzeba latwe i szybkie rozwiazanie tego problemu
#include <vector> std::vector <rekord> rek;
Tutaj opis: http://www.cplusplus.com/reference/stl/vector/
grzesiek - 10-01-2008 18:52
te biblioteki odwalą za ciebie całą robotę, to właśnie bez nich będziesz siedział w bugach ;) i czas tracił poza tym nie są takie nowe mają ponad 20 lat ;)
skotik87 - 10-01-2008 18:59
te biblioteki odwalą za ciebie całą robotę, to właśnie bez nich będziesz siedział w bugach ;)
heh wlasnie wzialem sie za ta klase, sprobuje cos napisac i wrzuce na forum, zobaczycie czy dobrze. poki co to opornie mi idzie, chyba za duzo na dzisiaj tego wszystkiego.
AdeBe - 10-01-2008 19:58
Słuchaj ludzi! Biblioteka STL załatwi to za Ciebie dużo szybciej i lepiej. Uwierz mi, że więcej czasu spędzisz na wymyślanie własnego rozwiązania, niż na naukę jednego tylko elementu z tej biblioteki. Vectory są wspaniałym wynalazkiem
skotik87 - 10-01-2008 21:50
wrocilem z browarka i jakos zaczelo mi to wszystko chodzic ;p jaki bedzie najlepszy sposob na wczytywanie danych w funkcji?? probowalem to robic na kilka sposobow i zaden mi nie dziala. jezeli jest to stala wartosc to dziala, a jezeli sam chce ja podac to kupa. chce to wczytywac tak jak to robilem wczesniej, czyli cos tego typu:
for(int i=0;i<n;++i) { cout << "imie: "; cin >> rek[i].imie; cout << "nazwisko: "; cin >> rek[i].nazwisko; cout << "telefon: "; cin >> rek[i].telefon; }
mlyczek - 10-01-2008 22:04
Nie wiemy nic o tym jakiego typu jest rek (czyli jakie pola w sobie zawiera), więc nie bardzo mogę wywnioskować co w powyższym jest źle. Może n jest większe od rozmiaru rek i wychodzi Ci pętla poza zakres? Tą stałą wartość jak odajesz?
rek[i].imie = "Jan";
? Jakie błędy wywala Ci przy w/w wczytywaniu?
skotik87 - 10-01-2008 22:19
wrzucilem caly pliczek do zalacznika na ktorym to testuje. najlepiej jak sam to uruchomisz to wtedy dokladnie zobaczysz. w strukturze wszystko jest na int bo narazie to musze zobaczyc jak to dziala, a pozniej bede sie dopiero bawil z reszta
mlyczek - 10-01-2008 23:36
no więc tak, program wywala się, bo do funkcji wektor przekazywany jest przez wartość, czyli vector a w Twojej funkcji stworz, to jest kopia vectora a z funkcji main, czyli wszystkie działania przeprowadzone w funkcji stworz sa robione na tej kopii lokalnej, ktora po zakonczeniu funkcji jest kasowana. Ty później chcesz ten vector a wypisać, ale on jest pusty, bo nic do niego nie dodałeś, dlatego program się wywala, bo odwołujesz się do pamięci, w której nic nie ma.
Program możnaby dużo lepiej napisać, ograniczę się jednak tylko do funkcji dla Ciebie kluczowej, teraz powinno to działać (mi działa).
void stworz(vector<rekord> &a, int n) { rekord temp; for(int i=0;i<n;++i) { cout << "imie: "; cin >> temp.imie; cout << "nazwisko: "; cin >> temp.nazwisko; cout << "telefon: "; cin >> temp.telefon; a.push_back(temp); } }
A więc krótko o funkcji. Najpierw tworze sobie nową zmienna typu rekord, do wczytywania danych. Do niej wczytuje po kolei dane i później dodaję ją do vectora a.push_back(temp). Reszta jest jasna. Najważniejszą zmianą w tej funkcji jest dodanie & przed a w nagłówku funkcji. Jest to dosyć trudne pojęcie w c++ (przynajmniej na początku), ale stanowi o jego mocy. W skrócie do funkcji przekazywany jest adres vectora a w pamieci, więc teraz wszystkie odwołania do a w funkcji nie odnoszą się do kopii lokalnej, ale do adresu parametru jej przekazanej, więc elementy dodawane są do vectora a z funkcji main (trochę nieszczęśliwie dobrałeś sobie oznaczenia, lepiej nie oznaczać zmiennych lokalnych i argumentow funkcji tymi samymi literkami, bo może to komplikować czytanie programu i narzucać myślenie, że to ta sama zmienna.
Mam nadzieję, ze nie zamieszałem za bardzo :) zmiany są tylko w w/w funkcji, wiec nie załączam ponownie tego pliku, bo wygląda on identycznie za wyjątkiem tego co tu napisałem.
skotik87 - 11-01-2008 19:47
mlyczek wielki browar dla ciebie za oswiecenie mnie ;p takiej odpowiedzi oczekiwalem. dobrze to wytlumaczyles przynajmniej w porownaniu z kolesiem na mojej uczelni hehe teraz sie biore za sortowanie (juz widze ze sporo bedzie trzeba zmienic), zapis i odczyt z/do pliku dziala tak jak powinien.
mlyczek - 12-01-2008 00:52
mlyczek wielki browar dla ciebie za oswiecenie mnie ;p takiej odpowiedzi oczekiwalem. dobrze to wytlumaczyles przynajmniej w porownaniu z kolesiem na mojej uczelni
no browara nie musisz mi dawać :P ale w końcu studiuje się informatykę, no i zainteresowania też się ma to można od czasu do czasu komuś pomóc.
skotik87 - 12-01-2008 18:03
to ja zrobie jeszcze malego oftopa. baza juz dziala chodz nie dokonca. ale nie w tym problem. probowalem ja jakos upiekszyc i jest zonk pod g++.
void gotoxy(int x, int y) { char essq[100]; char xstr[100]; char ystr[100]; sprintf(xstr, "%d", x); sprintf(ystr, "%d", y); essq[0] = '\0'; strcat(essq, "\033["); strcat(essq, ystr); strcat(essq, "d"); strcat(essq, "\033["); strcat(essq, xstr); strcat(essq, "G"); printf("%s", essq); }
void ramka() {int x1=1, x2=75, y1=1,y2=21; int i; for (i=x1; i<=x2; i++) { gotoxy(i,y1); printf("%c", 205); gotoxy(i,y2); printf("%c", 205); } gotoxy(75,1); printf("%c", 187); gotoxy(1,1); printf("%c", 201); gotoxy(1,21); printf("%c", 200); gotoxy(75,21); printf("%c", 188); for (i=y1+1; i<y2; i++) { gotoxy(x1,i); printf("%c", 186); gotoxy(x2,i); printf("%c", 186); } }
brakuje mi funkcji gotoxy, ale znalazlem cos takiego jak jest wyzej. wiec ok. ale jak chce narysowac ramke ze znakow ascii to wypisuje mi glupoty. pod builderem na winshicie dziala tak ja powinno. i moje pytanie czy jest jakas mozliwosc narysowania takiej ramki(lini) nie koniecznie ze znakow asciii zeby to jakos dzialalo?? wole kompilowac pod linuchem ale chyba bede zmuszony przejsc na buildera z tego powodu..
mlyczek - 14-01-2008 15:57
Wypisujesz jakieś śmieszne znaki np. tutaj
printf("%c", 201);
nie bardzo wiem, jaki znak chciałeś tu wypisać, no i po co wypisywać znaki po ich kodach zamiast normalnie, czyli dla -, dajesz
printf("%c", '-');
skotik87 - 14-01-2008 19:28
dokladnie to chcialem zrobic cos takiego pod g++
http://img220.imageshack.us/my.php?i...eenshotgk8.jpg
ale cos czytalem ze z rozszerzonymi znakami ascii to nie da rady.
tak, ale to niezbyt ladnie wyglada, wolalbym ze znakami ascci. ale jak sie nie da to trudno
salmon - 14-01-2008 19:53
Jak chcesz żeby ładnie wyglądało to użyj bibliotek graficznych. Ja ze swojej strony polecam Qt, jak koniecznie chcesz pod konsolą to zainteresuj się ncurses.
skotik87 - 15-01-2008 00:16
Jak chcesz żeby ładnie wyglądało to użyj bibliotek graficznych. Ja ze swojej strony polecam Qt, jak koniecznie chcesz pod konsolą to zainteresuj się ncurses.
qt odpada w tym wypadku. ostatnio zainteresowalem sie wlasnie ncurses ale brak czasu nie pozwala na wprowadzenie tego do mojego projektu. chociaz jak znajde pare godzin to moze cos napisze sensownego.
[ Dodano: 2008-01-16, 22:45 ] struct laptop { char marka[4]; //nie ma roznicy czy to sa chary czy stringi char model[4]; double cena; double gwarancja; unsigned int ilosc; data data_wprow;
};
void wczytaj(vector<laptop> &a, int rozmiar) { ifstream plik_w; plik_w.open("/home/skotik/bazadanych/plik_w"); laptop temp; for(int i=0;i<rozmiar;++i) { plik_w>>temp.marka; plik_w>>temp.model; plik_w>>temp.cena; plik_w>>temp.ilosc; plik_w>>temp.gwarancja; plik_w>>temp.data_wprow.d; plik_w>>temp.data_wprow.m; plik_w>>temp.data_wprow.r; a.push_back(temp); } }
I kolejny maly problem ktorego nie moge rozwiazac. funkcja fajnie wczytuje z pliku, tylko nie wczytuje "liter" czyli. plik_w>>temp.marka; plik_w>>temp.model;
program sie zawiesza wtrakcie wywolywania tej funkcji gdy w pliku sa litery. gdy sa came cyfry dziala ok. czy o czyms waznym w wektorach nie wiem??
mlyczek - 16-01-2008 23:26
Ja bym mimo wszystko dał zamiast char marka[4] stringi, czyli string marka. Po to one są w C++, żeby ich używać, to nie jest czyste C, gdzie stringów nie ma i trzeba wszystko na char'ach robić. Nie pamiętam dokładnie jak C++ wczytuje ze strumienia stringi (albo tablice char'ow), wszystko wygląda dobrze. Pamietaj tylko, że operator >> czyta do białoego znaku, czyli jeśli będziesz miał w pliku coś takiego
jakas marka jakis model laptopa ... itd.
to powinno przypisać do marka napis jakas, a do model - marka, później do cena będzie chciał wczytać jakis, a to nie jest liczba. Nie bardzo widzę, gdzie tu może być innego typu niż wyżej napisałem błąd.
skotik87 - 22-01-2008 11:45
dobra tamat zamykam, wszystko dziala jak powinno. do tej pory nie wiem co byly bledem ze nie wczytywalo liter o_0 wrzuce caly moj program za jakis czas moze komus sie przyda
zanotowane.pldoc.pisz.plpdf.pisz.plminister.pev.pl
|