Forum Coders' city Strona Główna Coders' city
Nasza pasja to programowanie!
 

 PomocPomoc   SzukajSzukaj   UżytkownicyUżytkownicy   GrupyGrupy  RejestracjaRejestracja 
Archiwum starego forum + teoria    RSS & Panel/SideBar
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 

Potrzebuję szybkiej odpowiedzi na moje pytanie... Zasady

[c++] odczyt z pliku i przeciążenie operatora



 
Odpowiedz do tematu    Forum Coders' city Strona Główna -> C i C++
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
hunter44



Dołączył: 12 Maj 2016
Posty: 5

PostWysłany: Pon Wrz 05, 2016 2:40 pm  OP    Temat postu: [c++] odczyt z pliku i przeciążenie operatora Odpowiedz z cytatem Pisownia

Witam. Uczę się obiektówki. Zadaniem programu jest sworzenie listy z danymi piłkarzy.
Pojawił się problem już na sam koniec a mianowicie:
Chcę otworzyć plik i odczytać z niego dane piłkarzy a następnie dodać je na listę.
Plik txt wygląda tak:
Cytat:
Jan Kowalski, lat: 22, napastnik


I nie wiem w jaki sposób przeciążyć teraz operator aby poprawnie odczytał on z pliku dane. Oczywiście ten program na pewno dało by się zrobić bez użycia operatora przeciążenia, ale ja chcę akurat w taki sposób :/

Cały program:
Kod:

#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>

using namespace std;

struct Gracz { // struktura przechowuje dane piłkarza, oraz ma zdefiniowaną funkcję wypełniającą pola struktury
    string imie;
    string nazwisko;
    int wiek;
    string pozycja;

    

    friend istream & operator >>(istream & is, Gracz & Gracz) {

        cout << "\nImie: "; is >> Gracz.imie;
        cout << "Nazwisko: "; is >> Gracz.nazwisko;
        cout << "Wiek: "; is >> Gracz.wiek;
        cout << "Pozycja:"; is >> Gracz.pozycja;
        return is;
    }
};


class Druzyna {
    list < Gracz > team;
public:


    void dodaj_gracza() {
        Gracz gracz; // lokalna deklaracja obiektu
        cin >> gracz; // użycie przeciążonego operator>> ze struktury (wypełnia pola struktury)
        team.push_back(gracz);
        
    }

    friend ostream & operator <<(ostream & os, const Druzyna & Druzyna) {
        for (auto const & elem : Druzyna.team) {
            os << elem.imie << ' ' << elem.nazwisko <<", "<< "lat: "
                << elem.wiek << ", " << elem.pozycja;

        }
        return os;
    }

    

};


int main()
{
    Druzyna druzyna{}; // deklaracja obiektu klasy (z kontenerem)
    int flaga = 0;

    char switchOpcja{};
    do {
        cout << "1. Dodaj pilkarza" << endl;
        cout << "2. Pokaz liste" << endl;
        cout << "3. Zapisz do pliku" << endl;
        cout << "4. Wczytaj z pliku" << endl;
        cout << "5. Zakoncz" << endl;
        cin >> switchOpcja;
        switch (switchOpcja) {
        case '1'://1.dodaj pilkarza
        {
            druzyna.dodaj_gracza();
            flaga = 1;

            break;
        }
        case '2'://2.pokaz liste
        {
            if (flaga == 0) cout << "Lista jest pusta kolego. Najpierw kogos dodaj" << endl;
            cout << druzyna << '\n';
            break;
        }
        case '3'://3.zapisz do pliku
        {
            if (flaga == 0) cout << "Chlopie ! Co TY chcesz zapisac skoro nie stworzyles listy ?" << endl;
            fstream plik;
            plik.open("lista.txt", ios::out | ios::app);
            plik << druzyna;
            plik.close();



            break;
        }

        case '4'://otworz z pliku
        {
            ifstream plik;
            plik.open("lista.txt");
            if (plik.good() == false) { cout << "Plik nie istnieje\n" << endl; break; }



            while (true)
            {
                flaga = 1;
                if (plik.good())
                {
                    
                    // i nie mam pojęcia co tutaj wpisać. Oczywiscie wczesniej powinienem przeciazyc operator ifstream, ale jak probowalem samemu to nie wychodzilo

                }
                else
                    break;


            } //while
            plik.close();
        }

        break;
        case '5'://zakoncz
        {cout << "Koniec.\n";

        break;
        }
        default:
        {
            cerr << "Jakis nieokreslony przypadek.\n";
        }
        }
    } while (switchOpcja != '5');



    system("PAUSE");


    return 0;

}


Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
lethern



Dołączył: 09 Paź 2007
Posty: 1106

PostWysłany: Pon Wrz 05, 2016 3:00 pm      Temat postu: Odpowiedz z cytatem Pisownia

Zwrócę wpierw uwagę na jeden błąd - tworzysz funkcję "wczytującą", która "wypisuje", to nie ma sensu i nie możesz tak robić (robić funkcję która nazywa się A, ale zamiast tego robi B lub robi kilka rzeczy) (szczególnie na przyszłość, bo w programie do zabawy oczywiście to nie robi krzywdy)
może kod wytłumaczy co mam na myśli
Kod:

friend istream & operator >>(istream & is, Gracz & Gracz) {
    is >> Gracz.imie;
    is >> Gracz.nazwisko;
    is >> Gracz.wiek;
    is >> Gracz.pozycja;
    return is;
}
    
void print(){
    cout << "\nImie: "+imie;
    cout << ", Nazwisko+nazwisko:
    cout << ", Wiek: "+wiek;
    cout << ", Pozycja: "+pozycja;
}

// w kodzie używasz obu funkcji



Główny problem jest taki, że próbujesz wczytać linię w której dane masz rozdzielone przecinkami, podczas gdy domyślne działanie operatora >> rozdziela dane spacją...
Czyli tekst
Cytat:
Ala, ma kota.

przy kodzie
Kod:
stream >> a1 >> a2 >> a3

wczyta
Cytat:
a1="Ala,"
a2="ma"
a3="kota."


link: http://stackoverflow.com/questions/18907007/override-istream-operator-and-modify-delimiter

_________________
używasz Dev-Cpp? tools->editor options -> use tab character (włącz), smart tabs (wyłącz)... albo ściągnij np. Visual Studio C++ free.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
hunter44



Dołączył: 12 Maj 2016
Posty: 5

PostWysłany: Pon Wrz 05, 2016 3:46 pm  OP    Temat postu: Odpowiedz z cytatem Pisownia

W linku, który podałeś jest rozwiązanie, ale ono u mnie nie zadziała. Tam jest pętla for i w programie nie ma wcale przeciążeń. Natomiast w moim programie oparte jest to na przeciążeniach. Chyba, że ja już coś mylę....
Skoro u mnie problemem jest przecinek to mogę go usunąć aby były seperatory, ale nadal nie wiem jak wczytać z pliku poprzez przeciążenie.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
lethern



Dołączył: 09 Paź 2007
Posty: 1106

PostWysłany: Pon Wrz 05, 2016 4:14 pm      Temat postu: Odpowiedz z cytatem Pisownia

Pewnym rozwiązaniem jest
Kod:
getline(cin, value, ',');

rozdzieli dane po przecinku (trzeci parametr)

np. w tym linku to jest http://stackoverflow.com/questions/1474790/how-to-read-write-into-from-text-file-with-comma-separated-values

[edit]
Po zobaczeniu całego kodu teraz rozumiem..
poniższy kod mi działa
Kod:
#include<iostream>
#include <string>
#include <process.h>
#include <list>
#include <cstddef>
#include <fstream>
#include<cstdlib>
#include <sstream>

using namespace std;

class Gracz { // struktura przechowuje dane piłkarza, oraz ma zdefiniowaną funkcję wypełniającą pola struktury
    string imie;
    string nazwisko;
    string wiek;
    string pozycja;

public:

    void wczytaj() {
        cout << "\nImie: "; cin >> imie;
        cout << "Nazwisko: "; cin >> nazwisko;
        cout << "Wiek: "; cin >> wiek;
        cout << "Pozycja:"; cin >> pozycja;
    }

    friend istream & operator >>( istream & is, Gracz & gracz ) {
        getline( is, gracz.imie, ',' );
        getline( is, gracz.nazwisko, ',' );
        getline( is, gracz.wiek, ',' );
        getline( is, gracz.pozycja, ',' );
        return is;
    }

    friend ostream & operator <<( ostream & os, Gracz const & gracz ) {
        os << gracz.imie << "," << gracz.nazwisko << "," << gracz.wiek << "," << gracz.pozycja << '\n';
        return os;
    }
};


class Druzyna {
    list < Gracz > team;

public:

    void dodaj_gracza() {
        Gracz gracz; // lokalna deklaracja obiektu
        gracz.wczytaj(); // użycie przeciążonego operator>> ze struktury (wypełnia pola struktury)
        team.push_back( gracz );
    }

    friend ostream & operator <<( ostream & os, const Druzyna & Druzyna ) {
        if( Druzyna.team.empty() )
            os << "Brak graczy";

        for( auto const & elem : Druzyna.team ) {
            os << elem;
        }
        return os;
    }

    friend istream & operator >>( istream & stream, Druzyna & druzyna ) {
        string line;
        while( getline( stream, line ) )
        {
            std::stringstream   linestream( line );

            Gracz gracz;
            linestream >> gracz;

            druzyna.team.push_back( gracz );
        }
        return stream;
    }

};


int main()
{
    Druzyna druzyna{}; // deklaracja obiektu klasy (z kontenerem)

    char switchOpcja{};
    do {
        cout << "1. Dodaj pilkarza" << '\n';
        cout << "2. Pokaz liste" << '\n';
        cout << "3. Zapisz do pliku" << '\n';
        cout << "4. Wczytaj z pliku" << '\n';
        cout << "5. Zakoncz" << '\n';
        cin >> switchOpcja;
        switch( switchOpcja ) {
            case '1'://1.dodaj pilkarza
            {
                druzyna.dodaj_gracza();
                break;
            }
            case '2'://2.pokaz liste
            {
                cout << druzyna << '\n';
                break;
            }
            case '3'://3.zapisz do pliku
            {
                fstream plik;
                plik.open( "lista.txt", ios::out  );
                plik << druzyna;
                plik.close();
                break;
            }

            case '4'://otworz z pliku
            {
                ifstream plik;
                plik.open( "lista.txt" );
                if( !plik.good() ) { cout << "Plik nie istnieje\n"; break; }

                druzyna={};

                plik >> druzyna;
                plik.close();
            }

            break;
            case '5'://zakoncz
            {
                cout << "Koniec.\n";
                break;
            }
            default:
            {
                cerr << "Jakis nieokreslony przypadek.\n";
            }
        }
    } while( switchOpcja != '5' );

    system( "PAUSE" );
    return 0;
}

_________________
używasz Dev-Cpp? tools->editor options -> use tab character (włącz), smart tabs (wyłącz)... albo ściągnij np. Visual Studio C++ free.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
hunter44



Dołączył: 12 Maj 2016
Posty: 5

PostWysłany: Pon Wrz 05, 2016 6:39 pm  OP    Temat postu: Odpowiedz z cytatem Pisownia

Dzięki. Działa pięknie, ale jeszcze tak z ciekawości:

Kod:

class Gracz { // struktura przechowuje dane piłkarza, oraz ma zdefiniowaną funkcję wypełniającą pola struktury
    string imie;
    string nazwisko;
    string wiek;
    string pozycja;



Wiek jest stringiem a nie intem. Gdy daję int to się nie kompiluje. Wniosek, że operator przepełnienia nie przyjmuje int ?
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
lethern



Dołączył: 09 Paź 2007
Posty: 1106

PostWysłany: Pon Wrz 05, 2016 6:52 pm      Temat postu: Odpowiedz z cytatem Pisownia

Uprościłem to fakt;
np. użyj stringa (zmienną pomocniczą) i przerobisz ją na inta odpowiednim sposobem (string to int)

_________________
używasz Dev-Cpp? tools->editor options -> use tab character (włącz), smart tabs (wyłącz)... albo ściągnij np. Visual Studio C++ free.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość Wyślij email
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Wto Wrz 06, 2016 1:36 pm      Temat postu: Odpowiedz z cytatem Pisownia

Zanim przejdę do dalszych kwestii: formaty danych do przetwarzania przez komputer powinny być projektowane tak, żeby nadawały się do tego celu. Obecny format* nijak tego warunku nie spełnia. Po co napis "lat:" przed wiekiem? Czy sądzisz, że komputer wie, co oznacza "lat"? Niepotrzebnie tylko komplikujesz w ten sposób temat. Gdyby tam mogła być dowolna kolejność pól albo pola były opcjonalne, przydatny byłby klucz do ich odróżniania. Jednakże ani ten format, ani twój kod nie dopuszczają takiej opcji. Drugą kwestią jest to, że format (a przynajmniej jego obraz, który można wyłuskać na podstawie przykładu) nie przewiduje nawet tak prostych sytuacji jak nazwisko "Thomas von Heesen". Po raz kolejny: komputer nie jest człowiekiem. Przechowujesz też informacje, które są nieaktualne niedługo po tym, gdy zostały wpisane. Mówię o wieku. Nie przechowuje się wieku, tylko np. datę urodzenia. Zacznij zatem od ustalenia sensownego formatu. Na przykład taki, który ma formę serii linii, z których każda opisuje piłkarza. Pojedynczy opis piłkarza ma postać oddzielonych precinkiem wartości: nazwisko, imię, data urodzenia w formacie YYYY/MM/DD oraz pozycja (Bramka, Obrona, Pomocnik, Atak). Przykładowo:
Cytat:
Tomaszewski,Jan,1948/01/09,Bramkarz
Szymanowski,Antoni,1951/01/13,Obrona
Gorgoń,Jerzy,1949/07/18,Obrona
Musiał,Adam,1948/12/18,Obrona
Bulzacki,Mirosław,1951/10/23,Obrona
Kasperczak,Henryk,1946/07/10,Pomocnik
Ćmikiewicz,Lesław,1947/05/03,Pomocnik
Deyna,Kazimierz,1947/10/23,Pomocnik
Lato,Grzegorz,1950/04/08,Atak
Domarski,Jan,1946/10/28,Atak
Gadocha,Robert,1946/01/10,Atak



Napisałeś "uczę się obiektówki", więc zacznę od tej strony. Czy faktycznie zadaniem programu jest tylko "sworzenie listy z danymi piłkarzy"? Jezeli tak, to zadanie zupełnie nie nadaje się do programowania obiektowego. To jest jeden use case: "stworzyć listę". Dodatkowo ma on z góry narzuconą implementację. Z tego powodu problem nie ma nic wspólnego z OOP, podobnie jak - z tej właśnie przyczyny - twój kod. Tam jest zwykłe programowanie strukturalne**.

Jeżeli chciałbyś się uprzeć i to obiektowo robić, to przede wszystkim brakuje ci metody lub klasy reprezentującej twój use case. Np. statczna metoda Team::loadFromStream(istream&) (Druzyna::zaladujZeStrumienia(istream&) po polskawemu, czego nie polecam) albo klasa odpowiedzialna za budowanie drużyny na podstawie danych ze strumienia. Ale do nauki obiektówki wybierz raczej coś, co daje szansę jej zastosowania.


Co do samego kodu:
  1. Linie 4 i 6: nieużywane nagłówki process.h oraz cstddef. Za szybko ci się program kompiluje?
  2. Linia 12: struct? Składniowo prawidłowe, tylko czy aby na pewno wiesz***, co to robi (czym się różni od class) i jesteś w stanie podać dobre uzasadnienie jego użycia? Wątpię.
  3. Linie 13-16: jakim prawem te pola są publiczne?
  4. Linia 15: przechowywanie wieku zamiast daty urodzenia.
  5. Linia 16: sugeruję użyć typu wyliczeniowego albo oddzielnej klasy reprezentującej pozycję. Pozycja nie jest dowolnym ciągiem znaków.
  6. Linie 12-28: klasa Gracz nie posiada żadnych metod pozwalających na niej operować. Równie dobrze mógłbyś napisać:
    Kod:
    class Gracz {};
    .
  7. W klasie Gracz pole wiek pozostaje niezainicjalizowane po utworzeniu obiektu. Obiekt nie jest prawidłowo inicjalizowany przez konstruktor.
  8. W klasie Gracz pola imie, nazwisko i pozycja nie mają żadnych senwoenych wartości po utworzeniu obiektu. Obiekt nie jest prawidłowo inicjalizowany przez konstruktor.
  9. Linia 32: czemu ::std::list zamiast ::std::vector?
  10. Linie 36-41: mieszanie różnych zagadnień. Czemu metoda klasy reprezentującej drużynę piłkarską zajmuje się obsługą komunikacji z użytkownikiem?
  11. Linie 37, 38, 59: komentarze nie służa do powtarzania tego, co jest napisane w kodzie, tylko wyjaśniania tego, czego w nim nie ma.
  12. Linia 59 i 62: po co {}?
  13. Linia 60 i 87: zmienne deklaruj na początku zakresu, w którym są używane.
  14. Linia 60: bezsensowna nazwa zmiennej.
  15. Linia 60: skoro ta zmienna może przyjmować tylko wartości reprezentujące prawdę i fałsz, to czemu to jest int zamiast bool?
  16. Linie 64-68, 80, 86 i 10: po co wypychasz dane ze strumienia (manipulator ::std::endl) w tym miejscu? Co więcej, w liniach 64-67 robisz to pomimo, że i tak linijkę dalej... wypisujesz kolejne dane.
  17. Linie 62, 69: do przechowywania liczb, które mają być wczytywane ze strumienia, proponuję raczej int, nie char. O ile liczby można przechowywać w dowolnym typie liczbowym, w tym char, o tyle liczby typu char mają dla biblioteki standardowej specjalne znaczenie i wszystkie funkcje na nich operujące traktują je jako znaki. Co zrobisz, gdy będziesz miał ponad 9 opcji i będziesz chciał nadal używać liczb do ich wyboru?
  18. Linie 71, 78, 84, 97 i 123: ze względu na odnoszenie się do pozycji w menu użycie gołych liczb jeszcze przejdzie i nie kwalifikuje się do magicznych liczb, ale mimo wszystko sensowniej byłoby użyć stałych lub typu wyliczeniowego.
  19. Linie 80, 86 i 101: nie bój się, naciśnięcie entera nie zepsuje ci klawiatury.
  20. Linie 80, 86 i 101: sprawdzasz warunek, informujesz o braku jego spełnienia, po czym... i tak nic z tym nie robisz. Wykonujesz operacje, przed których wykonaniem ten warunek miał chronić.
  21. Linie 80, 86 i 101: wypadałoby użyć ::std::cerr, nie ::std::cout. Zresztą trochę niżej już o tym wiedziałeś - czemu tutaj nie?
  22. Linie 87-88 i 99-100: po co rozbijasz na dwie linijki?
  23. Linia 87: proponuję raczej ::std::ofstream. Przy okazji zaoszczędzisz sobie podawania niepotrzebnych flag przy otwieraniu.
  24. Linia 88: czy aby na pewno chcesz otwierać plik w trybie ::std::ios::app? Dokładniej: jakie widzisz uzasadnienie tego trybu i - jeśli już - gdzie obsługa sytuacji, gdy plik zawiera już dane?
  25. Linie 90 i 119: plik i tak zostanie zamknięty linijkę dalej - nie musisz jawnie tego robić.
  26. Linia 101: po co porównujesz wartość typu bool z false? Sprawdzasz, czy false równa się false, po czym jeszcze to leci do konstrukcji, która i tak przyjmuje wartość true lub false. To porównanie jest całkowicie zbędne. Wystarczy: !plik.good(). W linii 108 już o tym wiedziałeś... czemu nie wiedziałeś o tym kilka linii wcześniej?

    A tak naprawdę wystarczy samo plik, bo strumienie są rzutowane na bool i to określa, czy nadają się do zpisu/odczytu, czy nie. Zatem:
    Kod:
    if (plik)
    {
        // ...
    }
  27. Jeśli robisz obsługę błędów, to rób ją kompletną albo wcale. W tej chwili w jednym miejscu robisz (np. w linii 101), w innych (np. linie 22-25, 45-46 i 89) - nie.
  28. Linia 105: użycie nieskończonej pętla. I nie, nie ma znaczenia, że w linii 115 robisz break. Do kontroli działąnia pętli służy jej warunek i tam powinno być ustalone, kiedy pętla się kończy.
  29. Linia 137: przeczytaj tego posta hobsona.
  30. Skoro masz już dołączone cstdlib, wypadałoby użyć EXIT_SUCCESS.


Ze względu na kiepski format danych będziesz też miał jeszcze inne kłopoty. Zwróć uwagę, co dzieje się ze spacjami przy zastosowaniu rozwiązania zaproponowanego przez letherna. Niestety, przy takim formacie musisz albo zrobić pełne parsowanie pliku, ręcznie ignorując białe znaki, albo po wczytaniu usunąć pocżątkowe i końcowe białe znaki ze stringa (jeśli występują) - też ręcznie, bo w C++ nie masz funkcji trim. Jesli wybierzesz pierwsze rozwiązanie, możesz spróbować zaimplementować własny manipulator. We wszystkich trzech przypadkach przyjęte rozwiązanie i tak nadal będzie błędne dla kodowań o zmiennej długości znaku - i w C++ sensownie tego nie rozwiążesz (kod będzie albo strasznie niewydajny, albo jeszcze straszniej skomplikowany).

Na razie dalej tematu nie rozwijam, bo zakładam, że dopiero zaczynasz - a prawidłowe rozwiązanie wymagałoby zagłębienia się w bardziej złożone aspekty biblioteki standardowej C++.
____
* Którego zresztą nie opisałeś. Zaledwie dałeś przykład, na podstawie którego możemy co najwyżej zgadywać, co miałeś na myśli.
** To, że użyłeś słowa class nie zmienia sprawy. Po prostu zmieniłeś zapis, ale znaczenie programu jest cały czas takie samo. O obiektówkę to się nawet nie otarło. Nawet nie ma metody, która odpowiadałaby temu use case'owi - co prawda jej obecnośc nie zrobiłaby z tego programu obiektowego, ale przynajmniej byłby nikły posmak tego zagadnienia.
*** Bez pytania google'a.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
hunter44



Dołączył: 12 Maj 2016
Posty: 5

PostWysłany: Czw Wrz 08, 2016 9:46 am  OP    Temat postu: Odpowiedz z cytatem Pisownia

Bardzo dziękuję za analizę tego kodu i za napisanie tych wszystkich uwag. Na pewno jeszcze raz na spokojnie zastanowię się nad tym wszystkim.
Mam jednak dwa pytania:
1. Jakie polecacie programy na początek, które są do rozwiązania typowo w obiektowy sposób, tak abym się nauczył obiektówki ?


2. Nie bardzo rozumiem ten fragment kodu. Jest przeciążony operator. No dobra, ale za co on odpowiada. Ten fragment ma pobrać dane z pliku i wpisać je na listę ?
Kod:

friend istream & operator >>(istream & stream, Druzyna & druzyna) {
        string line;
        while (getline(stream, line))
        {
            std::stringstream   linestream(line);

            Gracz gracz;
            linestream >> gracz;

            druzyna.team.push_back(gracz);
        }
        return stream;
    }

Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
marcin_an



Dołączył: 26 Maj 2005
Posty: 18822

PostWysłany: Czw Wrz 08, 2016 10:51 am      Temat postu: Odpowiedz z cytatem Pisownia

hunter44 napisał:
1. Jakie polecacie programy na początek, które są do rozwiązania typowo w obiektowy sposób, tak abym się nauczył obiektówki ?
Jeśli przy piłce nożnej jesteśmy: może to być chociażby prosty menedżer piłkarski, gdzie rekrutujesz/kupujesz/sprzedajesz piłkarzy, urządzasz im treningi i możesz wystawiać do drużyny na mecze (mecze rozstrzygane są losowo, z wzięciem pod uwagę cech i doświadczenia piłkarzy obydwu drużyn). Wystarczająco "duży" problem, żeby można było pokusić się o rozwiązanie obiektowe.

Twój obecny program program ma więcej rzeczy do robienia niż tylko wczytanie listy (jest to uproszczone zarządzanie bazą danych - co najmniej 4 przypadki użycia) i na siłę możnaby robić go obiektowo, ale zamiast zobaczyć zaletę obiektówki, dostałbyś kod, po którym miałbyś tylko jedną myśl: "co zyskuję piszą 10x więcej kodu, który jest o wiele bardziej skomplikowany i zdaje się być mniej wydajny?". A nie o to chodzi.

hunter44 napisał:
Nie bardzo rozumiem ten fragment kodu. Jest przeciążony operator. No dobra, ale za co on odpowiada. Ten fragment ma pobrać dane z pliku i wpisać je na listę ?
Nie z pliku, tylko z dowolnego strumienia (operatory >> i << przeciąża się dla dowolnego strumienia, odpowiednio ::std::istream oraz ::std::ostream*). Wczytuje on w pęli linie do stringa, a następnie każdego stringa wczytuje do obiektu Gracz. Nie bardzo wiem, po co kopiowanie do tymczasowego bufora, ale o to pytaj autora.

____
* Tak naprawdę można dla dowolnego std::basic_istream[/icode] i ::std::basic_ostream, ale pomińmy na razię tę kwestię.
Powrót do góry
Zobacz profil autora Wyślij prywatną wiadomość
Wyświetl posty z ostatnich:   
Odpowiedz do tematu    Forum Coders' city Strona Główna -> C i C++ Wszystkie czasy w strefie CET (Europa)

Strona 1 z 1

 
Skocz do:  
Możesz pisać nowe tematy
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Możesz dodawać załączniki na tym forum
Możesz pobierać pliki z tego forum




Debug: strone wygenerowano w 0.24186 sekund, zapytan = 11
contact

| Darmowe programy i porady Jelcyna | Tansze zakupy w Helionie | MS Office Blog |