Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Poziom 4, Rozdział 34, Zadanie 2

Ostatnio zmodyfikowano 2022-11-14 17:51
Autor Wiadomość
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:


C/C++
#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; } } }
P-179761
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.

C/C++
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; } } }
P-179762
Vena
Temat założony przez niniejszego użytkownika
» 2022-11-14 09:44:02
Dobra, dalej jest coś nie tak o.o
P-179763
DejaVu
» 2022-11-14 09:51:11
P-179764
Vena
Temat założony przez niniejszego użytkownika
» 2022-11-14 10:02:33
Dzięki! Zabieram się za przeglądanie tamtego tematu!
P-179765
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:

C/C++
#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
C/C++
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!
P-179766
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.
P-179768
« 1 »
  Strona 1 z 1