[Rozdział 34] Zadanie domowe 2 [ trudne ]
Ostatnio zmodyfikowano 2016-05-12 13:43
Aran_swiezak Temat założony przez niniejszego użytkownika |
[Rozdział 34] Zadanie domowe 2 [ trudne ] » 2016-03-21 20:51:05 Napisz program, który dla każdego wiersza w pliku: - wczyta liczby i wypisze ich sumę w przypadku, gdy wszystkie liczby uda się wczytać; - wypisze komunikat o błędnych danych, jeżeli wystąpi błąd podczas wczytywania liczb (komunikat ma wyświetlać numer wiersza, w którym wystąpił błąd). Program się kompiluje i działa prawidłowo do momentu wczytania ostatnich znaków w pliku, wtedy zamiast wykryć koniec pliku i zakończyć pętlę while nadal wczytuje dane(krzaki). Mimo wielu prób nie mogę znaleźć błędu więc proszę o pomoc. Być może warunek lub działanie metody eof klasy fstream nie jest przezemnie dobrze rozumiane. Oto moja funkcja odpowiedzialna za wczytywanie danych z pliku: bool wczytajPlik( string nazwaPliku ) { ifstream plik; plik.open( nazwaPliku.c_str() ); if( !plik.good() ) return false; if( plik.good() ) { string wiersz; cout << "Dane z pliku: " << endl; while( getline( plik, wiersz ) ) cout << wiersz << endl; cout << endl; plik.close(); } plik.open( nazwaPliku.c_str() ); int a; char x; int b = 0; int c = 1; bool czyBylyBledy = false; while( !plik.eof() ) { plik >> a; if( plik.good() ) b += a; if( !plik.good() ) { cout << "Bledne dane w wierszu nr " << c << "!" << endl; czyBylyBledy = true; plik.clear(); plik >> x; if( !plik.good() ) { cout << "Blad wczytywania danych! " << endl; return 0; } } if( czyNapotkanoZnakNowegoWiersza( plik ) ) { if( czyBylyBledy == false ) cout << b << endl; if( czyBylyBledy == true ) czyBylyBledy = false; b = 0; c++; } } return true; } |
|
carlosmay |
» 2016-03-22 06:01:00 Doczytanie do końca pliku nie ustawia EOF, dopiero próba odczytania czegoś, gdy wskaźnik odczytu jest na końcu pliku. Oprogramuj wczytywanie liczb w podobny sposób jak getlin() wcześniej. plik >> a >> x >> b |
|
Aran_swiezak Temat założony przez niniejszego użytkownika |
» 2016-03-22 13:39:27 Tak jak napisałeś doczytanie do końca pliku - wczytanie ostatniego znaku w pliku zakończone powodzeniem nie ustawia EOF jednak kolejną akcją jest próba wczytania kolejnego znaku (którego nie ma) i najwyraźniej wczytuje(tworzy?) krzaki. Jeśli chodzi o wczytywanie zasugerowane przez Ciebie to w przypadku gdy mam losową i różną ilość danych w każdym wierszu (mieszanka cyfr, liter i znaków) tego typu wczytywanie chyba mi nie pomoże - przykładowo gdy w wierszu będą 2 cyfry to trzecią pobierze z wiersza następnego. Poza tym wczytywanie pojedynczo znaków też musi zadziałać jeśli program wykryje w jakiś sposób koniec pliku a najwyraźniej próba wczytania znaku po końcu pliku go o tym nie uświadamia... |
|
carlosmay |
» 2016-03-22 18:19:03 Jeśli chodzi o wczytywanie zasugerowane przez Ciebie to w przypadku gdy mam losową i różną ilość danych w każdym wierszu (mieszanka cyfr, liter i znaków) tego typu wczytywanie chyba mi nie pomoże |
Tak. Jest podobne zadanie i pomyliłem się. { std::ifstream plik( "test.txt" ); if( plik.is_open() ) { int wiersz = 1; int suma = 0; char znak; bool flag; do { flag = true; suma = 0; while( !czyNapotkanoZnakNowegoWiersza( plik ) && !plik.eof() ) { if(( plik >> znak ) && isdigit( znak ) ) { suma += znak - '0'; } else { flag = false; while( plik.get() != '\n' ) continue; break; } } if( plik.eof() ) { break; } else if( flag ) { std::cout << suma << std::endl; } else { std::cout << "Bledne dane w wierszu " << wiersz << '!' << std::endl; } ++wiersz; } while( !plik.eof() ); } |
|
KrulTibianus |
» 2016-05-12 13:43:15 Pozwolę sobie (chyba nikt się nie obrazi:) odświeżyć temat i wrzucić tu swoje rozwiązanie. Po przeglądnięciu około 10 tematów z tym zadaniem, wreszcie udało mi się dojść do ostatecznego rozwiązania. Kluczowa była metoda ignore, która po wykryciu błędnej danej, pozwala na przejście do kolejnego wiersza. Minusem mojego rozwiązania jest brak rozbicia kodu na funkcje. W przeglądanych przeze mnie tematach kody były nieskończone, lub nie działały do końca jak powinny. To rozwiązanie może się komuś przydać. #include <iostream> #include <string> #include <fstream> #include <limits>
bool czyNapotkanoZnakNowegoWiersza( std::ifstream & plik ) { char cZnak; for(;; ) { plik.clear(); cZnak = plik.peek(); if( plik.fail() || plik.bad() ) return false; if( !isspace( cZnak ) ) return false; plik.get( cZnak ); if( plik.fail() || plik.bad() ) return false; if( cZnak == '\n' ) return true; } }
int main() { std::ifstream plik; int wiersz = 1; int wynik = 0; plik.open( "tekst.txt" ); if( !plik.fail() ) std::cout << "Udalo sie otworzyc plik.\n" << std::endl; else { std::cout << "Nie udalo sie otworzyc pliku."; return 0; } while( !plik.eof() ) { plik.clear(); int liczba; plik >> liczba; if( plik.bad() ) { std::cout << "Wystapil blad sprzetowy przy wczytywaniu liczby!" << std::endl; plik.close(); return 0; } if( plik.fail() ) { plik.clear(); std::cout << "Bledne dane w wierszu " << wiersz << std::endl; wiersz++; plik.ignore( std::numeric_limits < std::streamsize >::max(), '\n' ); wynik = 0; continue; } else { wynik += liczba; } if( czyNapotkanoZnakNowegoWiersza( plik ) || plik.eof() ) { std::cout << "Wynik w wierszu " << wiersz << " = " << wynik << std::endl; wiersz++; wynik = 0; } } plik.close(); return 0; }
|
|
« 1 » |