Open ksorokosz opened 8 years ago
i jeszcze jedna ciekawostka. a co się stanie jak plik daneklientow.baza będzie miał na początku 5 linii? program się zapętli ;) bo przeczytasz dane znajdujące się poza tablicą stringów i wtedy wartość: optlist[queue].length() może być bardzo duża, a na pewno nieznana.
jak widzisz tablice, zakresy w C++ mają całkiem duże znaczenie :) P.S pisałeś wcześniej w Pascalu prawda?
Nie, w Pascalu nie pisałem :smile: a to ci niespodzianka :smile: Ale kiedyś pisałem wsady systemowe i strony w HTMLu, ale to było dawno, ech, co za czasy... I jeszcze lubiłem grzebać w plikach gier, hehe. Potem przesiadłem się na Scratch. Oczywiście od dzieciństwa lubiłem czytać gazety komputerowe, najbardziej Komputer Świat i KS Ekspert. Na dobrą sprawę C++ jest moim pierwszym porządnym językiem programowania :wink: P. S. Kiedyś pisałem jakiś MidLet w Javie z poradnikiem Komputer Świat. Wtedy to było jeszcze tylko przepisywanie :smile:
Przeczytałem jeszcze raz Pański post. Może źle się wyraziłem. Chodzi o to, że w pliku na początku istnienia muszą istnieć co najmniej 4 linie, oczywiście może być ich więcej, wtedy menu automatycznie się wydłuży. Program testuję z takim oto przykładowym plikiem:
Bill Gates Obi-Wan Kenobi Harrison Ford Mark Zuckerberg Donald Duck Justin Bieber
Jak widać, zawiera on 6 linii. Będę musiał wstawić jeszcze kod do rozdzielania linii tekstu na czynniki pierwsze :smile:
@EMCsoftware dobrze to prześledźmy kod :)
6 linijek tak? dobra to pętla: for (queue = 1; queue <= repeats; queue++)
będzie od 1 do 6. zgadza się? 1 krok pętli: if(posopt == queue) -> to jest prawda więc wyświetli się kursor ">" a dalej klient
2 krok pętli: queue = 2 więc wchodzi do 47 linijki (i tak już do końca pętli): czyli: }else{ cout<<optlist[queue ]; for(int i = 1; i <= 21-optlist[queue ].length(); i++) { cout<<" "; } } dalej wyświetla się klient (i to jest prawidłowe!)
ale idźmy dalej. krok 3 -> wyświetli się: optionslist[3] = "Dodaj uzytkownika";// (bo optlist to w tej funkcji optionslist) krok 4 wyświetli się: optionslist[4] = "Zmien status ksiazki";// (tu jest już błąd bo poza tablicą, ale "zadziała" bo ustawiłeś wartość - o ile program się nie wywali)
krok 5 co się wyświetli po lewej stronie? cout<<optlist[queue ]; czyli optionslist[5]. Ile jest równe? Ano nie wiadomo ;) a dalej zobacz co masz: for(int i = 1; i <= 21-optlist[queue ].length(); i++)
sprawdzasz długość tego optionslist[5]. Jeśli pamięć jest zerem to zadziała, bo ta pętla się uruchomi dokładnie 21 razy, długość stringa pustego to zero. I spoko, tyle że u mnie w pamięci jest tam: E 0}E ╚ đI 0/G /G ( ( đI /G Ó/G ě I `łE đçE ╚ I P/G @/G ( ( I 0G
;) Rozumiesz?
Hej :) widać, że już dużo wiesz, ale chciałbym żebyś to usystematyzował :) dzięki temu zrobisz dużo fajnych rzeczy!
wektor również indeksujemy od zera - http://cpp0x.pl/kursy/Kurs-STL-C++/Kontener-tablicy-std-vector/119 (zobacz druga pętla i wyświetlenie wektora)
ale moja uwaga nie dotyczyła nawet wektora tylko zwykłej tablicy zobacz: linijka 126 LU.cpp optionslist[4] = "Zmien status ksiazki";// 4 element
niestety optionlist to jest zwykła tablica stringów - patrz linia 122 (ale przy wektorze również byłby to błąd) string optionslist[4];
Powód, dla którego musi istnieć plik jest tutaj: if(clients.size() <= 4) repeats = 4; else repeats = clients.size();
linijka 29 w LU.cpp. Ten kod mówi tyle: jeśli nie ma 4 klientów to tak czy inaczej uruchom pętlę niżej co najmniej 4 razy. To jest błąd projektowy właśnie.Czy ważniejsze jest to żeby program działał czy może ważniejsze jest to żeby działał tak jak użytkownik oczekuje? Wyobraź sobie grę komputerową, która wymagałaby stworzenia przez Ciebie jakiegoś pliku bez którego by się nie uruchomiła? Gdybym nie wczytał się w kod lub gdybyś mi nie powiedział po prostu nie zgadłbym że ten program potrzebuje 4 linii. To są właśnie tory nad przepaścią ;) Wiszą wiszą, ale żaden pociąg nie przejedzie.
a dlaczego Ci działało z błędnymi indeksami? zobacz co napisałeś np. linijka 63 LU.cpp: for(int i = 1; i <= 21-clients[queue - 1].length()-1; i ++)
queue zmienia się od 1 do 4 włącznie. czyli jakie wartości odczytujesz z wektora clients? queue = 1 => clients[queue - 1] = clients[0] queue = 2 => clients[1] ... queue = 4 => clients[3]
i jest dobrze ;) tutaj indeksy są poprawne, choć nakombinowałeś bardzo dużo. W pętli liczysz od 1, a potem odejmujesz, ale dlaczego liczysz od 1... bo tablica stringów, o której wcześniej pisałem też indeksujesz od 1... a potem pozycje kursora również indeksujesz od 1. I tak najbardziej skrajną górną jest "1", najbardziej skrajną dolną jest 4, a powinno być 0 i 3. Porównaj linijki: 183 (tutaj przypisujesz 4) oraz 178 (tutaj ustawiasz 1, bo warunek pozwala tam wejść tylko wtedy gdy menuoptionsposition = 2)
a więc tutaj też jest błąd indeksowania :)
a teraz dlaczego Ci się prawidłowo wyświetla: ponieważ wszystko ustawiasz na wartości takie jakie mają się wyświetlić tzn. linijka 126: optionslist[4] = "Zmien status ksiazki";// 4 element
tutaj ustawiasz komórkę pamięci o jeden za tablicą! ustawiasz ją! czyli zmieniasz jej zawartość. Na Twoim komputerze, w Twojej pamięci w tym miejscu nie ma nic ważnego i program się uruchamia, po prostu pisze po czymś po czym nie powinien, a potem czyta coś czego nie powinien to tak jakbyś: ucząc się na sprawdzian z matematyki zrobił ściągę -> w tym momencie napisałeś coś czego nie powinieneś a potem ściągał -> w tym momencie przeczytałeś coś czego nie powinieneś.
i od szczęścia zależy czy Ci się uda. Raz się uda, raz nie. Prawda? Tutaj jest taki sam przypadek. U ciebie działa, bo nic ważnego nie nadpisujesz w tej pamięci, u mnie nie bo być może trafia na inny program albo system operacyjny. Być może jakbyś uruchomił ten program 20 razy pod rząd raz by się wywalił, innym razem uruchomił.
I teraz trzeba to wszystko odkręcić :) Spróbujesz to zrobić sam? Jak już to zrobisz powiem Ci o tym pliku :)