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

Lekcja 34 Zadanie 2.

Ostatnio zmodyfikowano 2014-07-07 20:14
Autor Wiadomość
Haryen
Temat założony przez niniejszego użytkownika
Lekcja 34 Zadanie 2.
» 2014-07-07 15:46:11
Cześć! Mam problem z zadaniem domowym z lekcji 34. Wszystko działa dobrze, ale źle wczytuje jedną linię.
Plik do wczytania:

1 2 3
3 4 a 5
3 2
5 2 2 1 3
# 3 4

Problem pojawia się w linii "3 4 a 5". Prawidłowo pokazuje, że są błędne dane jednak przy następnym obiegu pętli wczytuje 5 z tej samej linii czego wynikiem jest:

6
Bledne dane w wierszu nr 2!
5
5
13
Bledne dane w wierszu nr 5!

A powinno być:

6
Bledne dane w wierszu nr 2!
5
13
Bledne dane w wierszu nr 5!

Kod:
C/C++
//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).
#include <iostream>
#include <fstream>
#include <string>

bool czyNapotkanoZnakNowegoWiersza( std::ifstream & plik )
{
    char cZnak;
    for(;; ) //nieskończona pętla
    {
        plik.clear();
        cZnak = plik.peek(); //sprawdzamy jaki kolejny znak zostanie zwrócony przez operację odczytu
        if( plik.fail() || plik.bad() )
             return false; //wystąpił błąd odczytu danych
       
        if( !isspace( cZnak ) )
             return false; //pobrany znak nie jest białym znakiem
       
        plik.get( cZnak ); //odczytujemy biały znak z pliku
        if( plik.fail() || plik.bad() )
             return false; //wystąpił błąd odczytu danych
       
        if( cZnak == '\n' )
             return true;
       
    } //for
}

bool odczytajPlik( std::string sNazwaPliku )
{
    std::ifstream plik;
    plik.open( sNazwaPliku.c_str() );
    if( !plik.good() )
         return false;
   
    int liczba, suma = 0, wiersz = 1;
    while( !plik.eof() )
    {
        plik >> liczba;
       
        if( plik.fail() )
        {
            std::cout << "Bledne dane w wierszu " << wiersz << "!" << std::endl;
            if( plik.fail() && !( czyNapotkanoZnakNowegoWiersza( plik ) ) ) //Jeśli plik fail i nie napotkano nowego wiersza to omin nastepna liczbe ale nie wiem jak :P
           
           
                 suma = 0;
           
            plik.clear();
            plik.get();
            continue;
        }
        else
        {
            suma += liczba;
            if( czyNapotkanoZnakNowegoWiersza( plik ) )
            {
                wiersz++;
                std::cout << suma << std::endl;
                suma = 0;
            }
        }
    }
    return true;
}

int main()
{
    if( !odczytajPlik( "plik.txt" ) )
         std::cout << "Nie udalo sie odczytac pliku!" << std::endl;
   
    return 0;
}

Jak to naprawić?
P-113428
pekfos
» 2014-07-07 17:27:51
C/C++
//Jeśli plik fail i nie napotkano nowego wiersza to omin nastepna liczbe ale nie wiem jak :P
ignore(), albo getline().
P-113436
Haryen
Temat założony przez niniejszego użytkownika
» 2014-07-07 17:49:55
Ok, ale gdzie to umieścić? Kiedy robię tak to nie działa, bo rozpoczyna się kolejny obieg pętli, więc i tak to wczytuje:

C/C++
#include <iostream>
#include <fstream>
#include <string>

bool czyNapotkanoZnakNowegoWiersza( std::ifstream & plik )
{
    char cZnak;
    for(;; ) //nieskoñczona pêtla
    {
        plik.clear();
        cZnak = plik.peek(); //sprawdzamy jaki kolejny znak zostanie zwrócony przez operacjê odczytu
        if( plik.fail() || plik.bad() )
             return false; //wyst¹pi³ b³¹d odczytu danych
       
        if( !isspace( cZnak ) )
             return false; //pobrany znak nie jest bia³ym znakiem
       
        plik.get( cZnak ); //odczytujemy bia³y znak z pliku
        if( plik.fail() || plik.bad() )
             return false; //wyst¹pi³ b³¹d odczytu danych
       
        if( cZnak == '\n' )
             return true;
       
    } //for
}

bool odczytajPlik( std::string sNazwaPliku )
{
    std::ifstream plik;
    plik.open( sNazwaPliku.c_str() );
    if( !plik.good() )
         return false;
   
    int liczba, suma = 0, wiersz = 1;
    while( !plik.eof() )
    {
        plik >> liczba;
        if( plik.fail() )
        {
            std::cout << "Bledne dane w wierszu " << wiersz << "!" << std::endl;
            suma = 0;
            if( !czyNapotkanoZnakNowegoWiersza( plik ) )
                 std::cin.ignore();
           
            plik.clear();
            plik.get();
        }
        else
        {
            suma += liczba;
            if( czyNapotkanoZnakNowegoWiersza( plik ) )
            {
                wiersz++;
                std::cout << suma << std::endl;
                suma = 0;
            }
        }
    }
    return true;
}

int main()
{
    if( !odczytajPlik( "plik.txt" ) )
         std::cout << "Nie udalo sie odczytac pliku!" << std::endl;
   
    return 0;
}

Ten sposób z getline() działa:
C/C++
#include <iostream>
#include <fstream>
#include <string>

bool czyNapotkanoZnakNowegoWiersza( std::ifstream & plik )
{
    char cZnak;
    for(;; ) //nieskoñczona pêtla
    {
        plik.clear();
        cZnak = plik.peek(); //sprawdzamy jaki kolejny znak zostanie zwrócony przez operacjê odczytu
        if( plik.fail() || plik.bad() )
             return false; //wyst¹pi³ b³¹d odczytu danych
       
        if( !isspace( cZnak ) )
             return false; //pobrany znak nie jest bia³ym znakiem
       
        plik.get( cZnak ); //odczytujemy bia³y znak z pliku
        if( plik.fail() || plik.bad() )
             return false; //wyst¹pi³ b³¹d odczytu danych
       
        if( cZnak == '\n' )
             return true;
       
    } //for
}

bool odczytajPlik( std::string sNazwaPliku )
{
    std::ifstream plik;
    plik.open( sNazwaPliku.c_str() );
    if( !plik.good() )
         return false;
   
    int liczba, suma = 0, wiersz = 1;
    std::string linia;
    while( !plik.eof() )
    {
        plik >> liczba;
        if( plik.fail() )
        {
            suma = 0;
            std::cout << "Bledne dane w wierszu " << wiersz << "!" << std::endl;
            plik.clear();
            std::getline( plik, linia );
            wiersz++;
        }
        else
        {
            suma += liczba;
            if( czyNapotkanoZnakNowegoWiersza( plik ) )
            {
                wiersz++;
                std::cout << suma << std::endl;
                suma = 0;
            }
        }
    }
    plik.close();
    return true;
}

int main()
{
    if( !odczytajPlik( "plik.txt" ) )
         std::cout << "Nie udalo sie odczytac pliku!" << std::endl;
   
    return 0;
}
P-113438
pekfos
» 2014-07-07 20:05:47
Ok, ale gdzie to umieścić?
» Kurs C++ » Poziom 1Obsługa strumienia wejściowego lekcja
P-113452
Haryen
Temat założony przez niniejszego użytkownika
» 2014-07-07 20:14:43
Dobra, dzięki. Ten paragraf pominąłem, bo myślałem, że dotyczy tylko Linuksa. :)
P-113456
« 1 »
  Strona 1 z 1