Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Strony: 1
Witam,
I tym razem przybywam na forum z prośbą o udzielenie mi pomocy.
Część, która przysparza mi problemu polega na odczytaniu informacji (imię , nazwisko , oceny z 3 przedmiotów szkolnych) dla 10 osób z pliku tekstowego ,,uczniowie.txt"
Problem: jedynie informacje o ostatniej osobie wpisanej w plik tekstowy zostają przekazane do kompilatora / zamiast wszystkich 10 osób.
#include <iostream> #include <cstdlib> #include <string> #include <fstream> using namespace std; class Dane_Ucznia { private: string imie , nazwisko; int matematyka , fizyka , informatyka; public: Dane_Ucznia (string imie_, string nazwisko_, int matematyka_, int fizyka_, int informatyka_); void Male_Intro(); void Srednia_Ocen_Ucznia(); void Srednia_Ocen_Uczniow(); void Zapisz_Do_Pliku(); void Wczytaj_Z_Pliku(); void Wypisz_Dane(); }; Dane_Ucznia :: Dane_Ucznia (string imie_, string nazwisko_, int matematyka_, int fizyka_, int informatyka_): //Konstruktor imie(imie_), nazwisko(nazwisko_), matematyka(matematyka_), fizyka(fizyka_),informatyka(informatyka_){} void Dane_Ucznia :: Male_Intro() { cout <<"****************************************************************************" <<endl; cout <<"** PROGRAM #1 - Liczenie sredniej z trzech przedmiotow dla 10 uczniow **" <<endl; cout <<"****************************************************************************" <<endl; } void Dane_Ucznia :: Wczytaj_Z_Pliku() { Dane_Ucznia * Tablica_Uczniow[10]; // Tworzenie tablicy ifstream Plik_Tekstowy("c://uczniowie.txt"); if (Plik_Tekstowy.is_open()) { while (Plik_Tekstowy.good())//do konca pliku { for (int i=1 ; i <= 10; i++) { Plik_Tekstowy >> imie; Plik_Tekstowy >> nazwisko; Plik_Tekstowy >> matematyka; Plik_Tekstowy >> fizyka; Plik_Tekstowy >> informatyka; Tablica_Uczniow[i]= new Dane_Ucznia(imie, nazwisko, matematyka, fizyka, informatyka); } } } } void Dane_Ucznia :: Wypisz_Dane() { Dane_Ucznia * Tablica_Uczniow[10]; // Tworzenie tablicy for (int i= 0; i < 10 ; i++) { cout <<imie <<endl; cout <<nazwisko <<endl; cout <<matematyka <<endl; cout <<fizyka <<endl; cout <<informatyka <<endl; } } void Dane_Ucznia :: Srednia_Ocen_Ucznia() { } void Dane_Ucznia :: Srednia_Ocen_Uczniow() { double Srednia; for (int i= 0; i < 10 ; i++) { cout <<""<<endl <<endl; Srednia = ((matematyka + fizyka + informatyka)/30); cout <<"SREDNIA OCEN DLA CALEJ KLASY WYNOSI = " << Srednia; } } void Dane_Ucznia :: Zapisz_Do_Pliku() { } int main () { Dane_Ucznia jeden ("","",0,0,0); jeden.Male_Intro(); jeden.Wczytaj_Z_Pliku(); jeden.Wypisz_Dane(); /* jeden.Srednia_Ocen_Uczniow();*/ system("PAUSE"); return 0; }
Dodatkowe informacje:
* Informacje pobierane są z pliku tekstowego - uczniowie.txt
* Informacje odczytywane są w postaci słowo za słowem (Oddzielone miedzy sobą spacja)
Zawartość pliku uczniowie.txt:
Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Jan kowalski 3 2 1 Marcin kowalski 3 2 1
Serdecznie dziękuję za ewentualną pomoc.
Ostatnio edytowany przez lubiekoty1 (2012-03-03 19:19:08)
Offline
Witam na formu.
Jako tako działający program wygląda tak:
#include <iostream> #include <cstdlib> #include <string> #include <fstream> using namespace std; class Dane_Ucznia { private: string imie , nazwisko; int matematyka , fizyka , informatyka; Dane_Ucznia * Tablica_Uczniow[10]; // Tworzenie tablicy public: Dane_Ucznia (string imie_, string nazwisko_, int matematyka_, int fizyka_, int informatyka_); void Male_Intro(); void Srednia_Ocen_Ucznia(); void Srednia_Ocen_Uczniow(); void Zapisz_Do_Pliku(); void Wczytaj_Z_Pliku(); void Wypisz_Dane(); }; Dane_Ucznia :: Dane_Ucznia (string imie_, string nazwisko_, int matematyka_, int fizyka_, int informatyka_): //Konstruktor imie(imie_), nazwisko(nazwisko_), matematyka(matematyka_), fizyka(fizyka_),informatyka(informatyka_){} void Dane_Ucznia :: Male_Intro() { cout <<"****************************************************************************" <<endl; cout <<"** PROGRAM #1 - Liczenie sredniej z trzech przedmiotow dla 10 uczniow **" <<endl; cout <<"****************************************************************************" <<endl; } void Dane_Ucznia :: Wczytaj_Z_Pliku() { //Dane_Ucznia * Tablica_Uczniow[10]; // Tworzenie tablicy ifstream Plik_Tekstowy("c://uczniowie.txt"); if (Plik_Tekstowy.is_open()) { while (Plik_Tekstowy.good())//do konca pliku { for (int i=0 ; i < 10; ++i) { Plik_Tekstowy >> imie; Plik_Tekstowy >> nazwisko; Plik_Tekstowy >> matematyka; Plik_Tekstowy >> fizyka; Plik_Tekstowy >> informatyka; Tablica_Uczniow[i]= new Dane_Ucznia(imie, nazwisko, matematyka, fizyka, informatyka); } } } } void Dane_Ucznia :: Wypisz_Dane() { //Dane_Ucznia * Tablica_Uczniow[10]; // Tworzenie tablicy for (int i= 0; i < 10 ; i++) { cout <<Tablica_Uczniow[i]->imie <<endl; cout <<Tablica_Uczniow[i]->nazwisko <<endl; cout <<Tablica_Uczniow[i]->matematyka <<endl; cout <<Tablica_Uczniow[i]->fizyka <<endl; cout <<Tablica_Uczniow[i]->informatyka <<endl; } } void Dane_Ucznia :: Srednia_Ocen_Ucznia() { } void Dane_Ucznia :: Srednia_Ocen_Uczniow() { double Srednia; for (int i= 0; i < 10 ; i++) { cout <<""<<endl <<endl; Srednia = ((matematyka + fizyka + informatyka)/30); cout <<"SREDNIA OCEN DLA CALEJ KLASY WYNOSI = " << Srednia; } } void Dane_Ucznia :: Zapisz_Do_Pliku() { } int main () { Dane_Ucznia jeden ("","",0,0,0); jeden.Male_Intro(); jeden.Wczytaj_Z_Pliku(); jeden.Wypisz_Dane(); /* jeden.Srednia_Ocen_Uczniow();*/ system("PAUSE"); return 0; }
Jednakże to jest nadal kod spaghetti :)
Błędy:
Po pierwsze, wielokrotnie tworzyłeś tablice uczniów, wewnątrz funkcji (zarówno na wczytywaniu jak i przy wypisywaniu, w tym drugim wypadku nawet nic z nią nie robiłeś, tylko sobie wisiała pusta ;] ), zamiast wyrzucić ją na zewnątrz do klasy - przez to wszystko się pierniczyło, bo na końcu zamiast wypisywać dane z zapełnionej tablicy, wypisywałeś ostatnie wczytane, które zawsze prezentowały ostatnią osobę.
Po drugie nie używaj konstrukcji w stylu:
for(int i=1;i<=10;i++)
bo:
1. Nie jest to wydajne/
2. Gubisz przy tym pierwszy element tablicy (tab[1]=costam jest pierwsze, a tablice idą w końcu od zera do i-1).
3. Wychodzisz za zadeklarowaną wcześniej wielkość tablicy (tab[10]=costam to odniesienie do jedenastego elementu tablicy, jeżeli deklarujesz tab[10] to tablica ma wartości od 0 do 9), co skończy się wysypaniem programu, prędzej czy później.
Poprawnie powinno to wygadać tak:
for(int i=0;i<10;++i)
Mniej porównań i komplikacji, a do tego preinkrementacja, która jest od postinkrementacji, szybsza (w pętlach w zasadzie chyba zawsze powinno się stosować preinkrementację, post jest stosowana znacznie rzadziej).
Po trzecie, stworzyłeś rekursywną klasę :D takiego dziwoląga widzę po raz pierwszy i powiedział bym wręcz że dziwne że to w ogóle działa :) . W przyszłości rozdziel sobie takie rzeczy na np. klasę daneUcznia, oraz klasę kontenerową np uczniowie, zawierająca tablicę z danymi ucznia. W tej drugiej implementujesz takie metody jak wczytaj, zapisz czy wyświetl, a w tej pierwszej sam konstruktor powinien styknąć.
To tyle ode mnie, u mnie po modyfikacji program działa, ale wycieki pamięci zapewne nadal jakieś są, więc nie zdziw się jak się na innym kompie sypnie, najlepiej popraw tak jak napisałem, wtedy będzie od razu lepiej :)
Pozdro.
Offline
Bardzo dziękuje za pomoc :)
// Proszę o nie zamykanie tematu - Po drodze mogą wystąpić kolejne błędy z którymi nie będę mógł sobie poradzić.
Offline
@Huk, z tą większą szybkością preinkrementacji to trochę naciągane. Fakt, to jest dobry nawyk, ale dobry kompilator (jakim jest gcc) skompiluje do tego samego kodu, gdy nie przypisujemy nigdzie tej zmiennej. Sprawa jest chyba trochę inna z iteratorami.
Co do autora posta to bym się zapoznał na Twoim miejscu z STL-em i ogólnie zasadami jak poprawnie stosować klasy.
Offline
Z pewnością się zapoznam.
// Temat do zamknięcia program został dokończony bez żadnych problemów.
Offline
lubiekoty1 napisał(-a):
// Temat do zamknięcia program został dokończony bez żadnych problemów.
Nie mamy zwyczaju zamykać wątków (o ile ktoś nie rozrabia).
Offline
@panjandrum:
Czy ja wiem? Na uczelni jeszcze kilka lat wstecz, chyba na poziomie assemblera było widać że dla post trzeba było (co zresztą logiczne) gdzieś tą wartość zapisać, zwiększyć i na końcu przepisać, podczas gdy dla pre wystarczyło tylko zwiększyć, być może nowsze wersje GCC/G++ wykrywają czy ma to jakiś wpływ na logikę i potrafią odpowiednie "poprawić" za usera (albo po prostu kompy są na tyle szybkie że dla większości programów nie ma to aż takiego znaczenia), ale IMHO lepiej jawnie mu to zapisać i być pewnym że zadziała o te parę operacji szybciej :)
Do autora: tak jak @panjandrum pisze: STL, podstawy klas itd - jak początkujący to polecam Symfonię C++ Grębosza, IMHO jedna z najlepszych książek na początek. Polecam tez OD RAZU zaopatrzyć się w jakiś normalny edytor z uzupełnianiem kodu, debugerem i podobnymi pierdołami. QTCreator jest na tę chwilę chyba janbardziej uniwersalny, obsługuje zarówno czyste projekty C++, jak i QT, posiada graficzną nakładkę na GDB, jak i na Valgrinda. Polecam.
W ogóle, polecam zapoznać się z QT i wszelkie projekty w tym kminić, lepszego framweorka pod C++ raczej nie znajdziesz :] (wiem wiem, fanboy ze mnie - ale taka prawda).
Pozdro.
Offline
Strony: 1