Vena Temat założony przez niniejszego użytkownika |
Poziom 4, Rozdział 34, Zadanie 2 » 2022-11-14 00:42:22 Hej, właśnie próbuję wykonać zadanie 2, z 34 rozdziału kursu. De facto korzystając z dotychczasowej wiedzy z kursu udało mi się wszystko ogarnąć, żeby działało. Dodałem pętle, która jest opisana jako "gotowa" w tym rozdziale kursu i ni cholery nie chce ona poprawnie działać. Może ktoś z was będzie miał jakiś pomysł. Troszeczkę pozmieniałem tylko nazewnictwo. Oto kod: #include <iostream> #include <string> #include <fstream>
int main() { const std::string str_data = "data.txt"; bool load_data( std::string ); if( !load_data( str_data ) ) { std::cout << "data.txt couldn't be read" << std::endl; } return 0; }
bool load_data( std::string str_data ) { std::ifstream fData; fData.open( str_data ); int iInteger = 0; int iSum = 0; int i = 1; bool isNewLine( std::ifstream & ); bool bWrongLine = false; while( true ) { fData >> iInteger; if( fData.fail() &&( !fData.eof() ) ) { if( fData.bad() ) { fData.close(); return false; } bWrongLine = true; fData.clear(); } if( fData.eof() ) { if( bWrongLine ) { std::cout << i << ". Line: data is corrupted!" << std::endl; break; } std::cout << i << ". Line: total sum is: " << iSum << std::endl; break; } if( fData.good() ) { iSum += iInteger; } if( isNewLine( fData ) ) { if( bWrongLine ) { std::cout << i << ". Line: data is corrupted!" << std::endl; } if( !bWrongLine ) { std::cout << i << ". Line: total sum is: " << iSum << std::endl; } iSum = 0; bWrongLine = false; i++; } } fData.close(); return true; }
bool isNewLine( std::ifstream & fData ) { char cChar; for(;; ) { fData.clear(); cChar = fData.peek(); if( fData.fail() ) { return false; } if( !isspace( cChar ) ) { return false; } fData.get( cChar ); if( fData.fail() ) { return false; } if( cChar == '\n' ) { return true; } } }
|
|
Vena Temat założony przez niniejszego użytkownika |
» 2022-11-14 09:26:18 Odnalazłem błąd w funkcji wstawionej przez autora kursu, nie jestem pewien, ale może wynika to ze zmiany standardów w cpp. Jedna z wywoływanych metod (.peek) zwraca wartość typu int, po usunięciu jej z kodu i przeformatowaniu pod .get, kod zaczął działać. Także, jeżeli ktoś napotka podobny problem, zostawiam tutaj poprawioną pętle. Mogę się mylić, jednak ta działa, a widziałem kilka identycznych problemów na forum. bool isNewLine( std::ifstream & fData ) { char cChar; for(;; ) { fData.clear(); fData.get( cChar ); if( fData.fail() ) { return false; } if( !isspace( cChar ) ) { return false; } if( cChar == '\n' ) { return true; } } }
|
|
Vena Temat założony przez niniejszego użytkownika |
» 2022-11-14 09:44:02 Dobra, dalej jest coś nie tak o.o |
|
DejaVu |
» 2022-11-14 09:51:11 |
|
Vena Temat założony przez niniejszego użytkownika |
» 2022-11-14 10:02:33 Dzięki! Zabieram się za przeglądanie tamtego tematu! |
|
Vena Temat założony przez niniejszego użytkownika |
» 2022-11-14 10:37:07 Zadanie udało się rozwiązać, chociaż nie w pełni wszystko rozumiem, cofam, to była moja głupota i pętla jak najbardziej działa poprawnie. Po wprowadzeniu poprawek jest prawie dobrze. Prawie, bo program dolicza dodatkową nieistniejącą linię, a zastosowałem się do wszystkiego co udało mi się znaleźć. Poza tym nie do końca rozumiem, co tak skaszaniłem w moim podejściu, bo logika wydawała mi się w porządku. To jest obecny kod: #include <iostream> #include <string> #include <fstream> #include <cstdio>
int main() { const std::string str_data = "data.txt"; bool load_data( std::string ); if( !load_data( str_data ) ) { std::cout << "data.txt couldn't be read" << std::endl; } return 0; }
bool load_data( std::string str_data ) { std::ifstream fData; fData.open( str_data ); int iInteger = 0, iSum = 0, i = 1; bool isNewLine( std::ifstream & ); std::string line; while( !fData.eof() ) { fData >> iInteger; iSum += iInteger; if( fData.fail() ) { iSum = 0; std::cout << i << ".Line: Data is corrupted!\n"; fData.clear(); std::getline( fData, line ); i++; } if( isNewLine( fData ) ) { std::cout << i << ".Line: Total sum is: " << iSum << std::endl; i++; iSum = 0; } } fData.close(); return true; }
bool isNewLine( std::ifstream & fData ) { char cChar; for(;; ) { fData.clear(); cChar = fData.peek(); if( fData.fail() || fData.bad() ) return false; if( !isspace( cChar ) ) return false; fData.get( cChar ); if( fData.fail() || fData.bad() ) return false; if( cChar == '\n' ) return true; } }
Dane wejściowe (data.txt): 1 2 3 3 4 a 5 3 2 5 2 2 1 3 # 3 4 1 1 2 3 3
I wynik: 1.Line: Total sum is: 6 2.Line: Data is corrupted! 3.Line: Total sum is: 5 4.Line: Total sum is: 13 5.Line: Data is corrupted! 6.Line: Total sum is: 2 7.Line: Total sum is: 2 8.Line: Total sum is: 6 9.Line: Data is corrupted!
Jak widać wciąż dolicza niewidzialną linię (9, a jest tylko 8) EDIT: Ok, znalazłem błąd, zostawiam dla potomnych. tutaj poprawka if( fData.fail() &&( !fData.eof() ) ) { iSum = 0; std::cout << i << ".Line: Data is corrupted!\n"; fData.clear(); std::getline( fData, line ); i++; }
Jeśli ktoś pokusi się o komentarz, byłbym bardzo wdzięczny, dzięki temu będę mógł zrozumieć dlaczego w ogóle tak :) Dzięki za podpowiedź @DejaVu! |
|
pekfos |
» 2022-11-14 17:51:25 Zadanie udało się rozwiązać, chociaż nie w pełni wszystko rozumiem, cofam, to była moja głupota i pętla jak najbardziej działa poprawnie. Po wprowadzeniu poprawek jest prawie dobrze. Prawie, bo program dolicza dodatkową nieistniejącą linię, a zastosowałem się do wszystkiego co udało mi się znaleźć. Poza tym nie do końca rozumiem, co tak skaszaniłem w moim podejściu, bo logika wydawała mi się w porządku. Twój pierwszy kod nie jest w stanie pozbyć się błędnego znaku. Usunięcie peek() zadziałało, bo wtedy funkcja z kursu zaczęła zawsze konsumować co najmniej jeden znak, zamiast pomijać tylko niektóre białe znaki. |
|
« 1 » |