K1cek Temat założony przez niniejszego użytkownika |
Najlepsze wyniki - return value 3221226356 » 2019-06-07 14:39:06 Witam, napisałem prostą grę. Mam problem z najlepszymi wynikami, funkcja która odpowiada za grę zwraca po jej zakończeniu wynik i nazwę gracza. Zapisuję te dane do pliku scores.txt pod postacią: Nazwa 123 Nazwa2 456 Teraz próbuję napisać funkcję, która wyciągnie te dane z pliku txt, posortuje i wyświetli 3 najlepsze wyniki. Funkcja tworzy 2 tablice, do jednej wrzuca imiona do drugiej wyniki. Ogólnie na wyjściu wszystko jest niby dobrze ale program kończy z return value 3221226356. Czy ma ktoś pomysł co może być nie tak albo jak inaczej zaimplementować te "najlepsze wyniki" ? #include <iostream> #include <fstream> #include <conio.h> #include <string> #include <sstream>
using namespace std;
void odczyt() { fstream plik; plik.open( "dane.txt", ios::in ); string linijka; if( plik.good() ) { int licznik = 0; while( !plik.eof() ) { getline( plik, linijka ); licznik++; } plik.clear(); plik.seekg( 0 ); int rozmiar = licznik / 2; string gracze[ rozmiar ]; int wyniki[ rozmiar ]; while( !plik.eof() ) { getline( plik, linijka ); gracze[ x ] = linijka; cout << "gracze[" << x << "] = " << gracze[ x ] << endl; getline( plik, linijka ); istringstream iss( linijka ); iss >> wyniki[ x ]; cout << "wyniki[" << x << "] = " << wyniki[ x ] << endl; x++; } plik.close(); } else { cout << "Error! Nie udalo się otworzyc pliku!" << endl; } } int main() { odczyt(); return 0; }
|
|
nanoant20 |
» 2019-06-07 15:24:22 gracze[ x ] = linijka; x - nieznane piszesz, że zapisujesz do scores.txt a otwierasz dane.txt |
|
pekfos |
» 2019-06-07 15:27:15 int rozmiar = licznik / 2; string gracze[ rozmiar ]; int wyniki[ rozmiar ]; |
Tak się nie tworzy tablic w C++. Tak się nie przechodzi po pliku w tej sytuacji. Wiesz dokładnie ile danych chcesz odczytać i ani trochę więcej. Jeśli wystąpi błąd odczytu, nie odczytasz niczego więcej, tym samym nigdy nie przerwiesz pętli i będziesz jechać po pamięci tak długo aż program się wysypie. Wczytuj dane w jednej pętli do pierwszego błędu odczytu, wczytuj do dynamicznie rozszerzalnej tablicy i oddaj sobie przysługę i trzymaj dane w jednej tablicy, a nie w dwóch. StrukturyKontener std::vector<> |
|
K1cek Temat założony przez niniejszego użytkownika |
» 2019-06-07 16:23:35 Rozumiem, że chodziło o coś w tym stylu ? A jeżeli jest to w miarę dobrze to jak teraz poruszać się po tych elementach i je posortować ? Oczywiście nie chodzi o gotowe rozwiązanie, poprostu nie wiem jaka jest składnia by chociaż wypisać te elementy, to dla mnie nowy temat. #include <iostream> #include <fstream> #include <conio.h> #include <string> #include <sstream> #include <iterator> #include <vector>
using namespace std;
struct DANE { string imiona; int wyniki; }; void Sortowanie( vector < DANE > vect ) { if( vect.empty() ) { cout << "\nBłąd, brak wartości."; } else { for( int count = 0; count < vect.size(); count++ ) { for( int count1 = 1; count1 < vect.size() - 1; count1++ ) { if( vect[ count1 - 1 ].wyniki < vect[ count1 ].wyniki ) { swap( vect[ count1 - 1 ], vect[ count1 ] ); } } } for( int i = 0; i < vect.size(); i++ ) { cout << "Imie - " << vect[ i ].imiona << " WYNIK " << vect[ i ].wyniki << endl; } } }
void odczyt() { vector < DANE > mojWektor; DANE Wyniki; fstream plik; plik.open( "dane.txt", ios::in ); string linijka; int helper; if( plik.good() ) { while( !plik.eof() ) { getline( plik, linijka ); Wyniki.imiona = linijka; getline( plik, linijka ); istringstream iss( linijka ); iss >> Wyniki.wyniki; mojWektor.push_back( Wyniki ); } Sortowanie( mojWektor ); plik.close(); } else { cout << "Error! Nie udalo otworzyc sie pliku!" << endl; } } int main() { odczyt(); return 0; }
. |
|
pekfos |
» 2019-06-07 16:29:44 Wszystkie odpowiedzi masz w dwóch lekcjach które podałem i w Wprowadzenie do standardowych algorytmów. Jeśli nie obsługujesz błędów, pętla ma się przerwać na pierwszym błędzie. Dopóki nie zaczniesz obsługiwać błędów, możesz zapomnieć o używaniu eof(). |
|
K1cek Temat założony przez niniejszego użytkownika |
» 2019-06-07 17:19:27 Dziękuje za odpowiedź pekfos. Udało mi się stworzyć coś takiego, działa i się kompiluje bez błędu. Gdyby ktoś jednak zauważył, że coś można było zrobić lepiej proszę o komentarz. #include <iostream> #include <fstream> #include <conio.h> #include <string> #include <sstream> #include <iterator> #include <vector>
using namespace std;
struct DANE { string imiona; int wyniki; }; void Sortowanie( vector < DANE > vect ) { if( vect.empty() ) { cout << "\nBłąd, brak wartości."; } else { for( int count = 0; count < vect.size(); count++ ) { for( int count1 = 1; count1 < vect.size() - 1; count1++ ) { if( vect[ count1 - 1 ].wyniki < vect[ count1 ].wyniki ) { swap( vect[ count1 - 1 ], vect[ count1 ] ); } } } for( int i = 0; i < vect.size(); i++ ) { cout << "Imie - " << vect[ i ].imiona << "WYNIK " << vect[ i ].wyniki << endl; } } }
void odczyt() { vector < DANE > mojWektor; DANE Wyniki; fstream plik; plik.open( "dane.txt", ios::in ); string linijka; int helper; if( plik.good() ) { while( !plik.fail() ) { getline( plik, linijka ); Wyniki.imiona = linijka; getline( plik, linijka ); istringstream iss( linijka ); iss >> Wyniki.wyniki; mojWektor.push_back( Wyniki ); } Sortowanie( mojWektor ); plik.close(); } else { cout << "Error! Nie udalo otworzyc sie pliku!" << endl; } } int main() { odczyt(); return 0; }
|
|
K1cek Temat założony przez niniejszego użytkownika |
» 2019-06-07 17:27:01 |
|
pekfos |
» 2019-06-07 17:41:51 void Sortowanie( vector < DANE > vect )
|
Przekazuj kontener przez referencję, by uniknąć niepotrzebnego kopiowania i faktycznie mieć posortowane dane po wywołaniu tej funkcji. for( int count = 0; count < vect.size(); count++ ) { for( int count1 = 1; count1 < vect.size() - 1; count1++ ) { if( vect[ count1 - 1 ].wyniki < vect[ count1 ].wyniki ) { swap( vect[ count1 - 1 ], vect[ count1 ] ); } } }
|
Gratuluję napisania sortowania - teraz możesz śmiało korzystać z gotowców. std::sort() działa szybciej niż twoje O(n 2) i krócej jest napisać kryterium sortowania i użyć gotowego algorytmu, niż pisać za każdym razem proste sortowanie od zera. while( !plik.fail() ) { getline( plik, linijka ); Wyniki.imiona = linijka; getline( plik, linijka ); istringstream iss( linijka ); iss >> Wyniki.wyniki; mojWektor.push_back( Wyniki ); } |
To nie jest technicznie rzecz biorąc najlepsze rozwiązanie. Tak na prawdę chcesz wczytać dane, potem sprawdzić błąd i na koniec dodać element do kontenera. Wczytując do pierwszego błędu raczej nie chcesz uwzględniać błędnego wpisu. Użycie istringstream jest też niebardzawe, lepiej od razu wczytywać int (ze wszystkimi konsekwencjami std::getline() mi nie działa!): while( true ) { getline( plik, Wyniki.imiona ); plik >> Wyniki.wyniki; if( plik.fail() ) break; plik.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); mojWektor.push_back( Wyniki ); } Zanim pomyślisz, że eof() mogłoby być w warunku pętli, to przypominam, że miałeś zapomnieć o eof(). eof() w tym wypadku byłoby zawsze prawdziwe, bo koniec pliku jest wykrywany gdy jest przyczyną błędu odczytu, więc przerwanie pętli na błędzie to wyłapie. Korzystając z tego, że std::getline() zwraca swój pierwszy argument, a strumień jest konwertowalny na wartość logiczną o wartości !fail(), można ten zapis skrócić do takiej pętli: while( getline( plik, Wyniki.imiona ) >> Wyniki.wyniki ) { plik.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); mojWektor.push_back( Wyniki ); } |
|
« 1 » 2 |