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

Lekcja 34 - zadanie 2.

Ostatnio zmodyfikowano 2014-06-27 19:20
Autor Wiadomość
Mateus.
Temat założony przez niniejszego użytkownika
Lekcja 34 - zadanie 2.
» 2014-06-26 11:55:19
Drugi raz mam problem. Polecenie:
2. [trudne zadanie] 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).
Przykładowe dane:

1 2 3
3 4 a 5
3 2
5 2 2 1 3
# 3 4
Oczekiwane standardowe wyjście programu dla przykładowego zestawu danych:

6
Bledne dane w wierszu nr 2!
5
13
Bledne dane w wierszu nr 5!
Wykorzystaj poniższą funkcję do wykrywania znaku przejścia do nowej linii:
C/C++
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
}
Powyższej funkcji nie wolno modyfikować.
Mój kod - trochę się go wstydzę, bo moim zdaniem jest głupi :-)
C/C++
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
bool czy( 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;
       
    }
}
void funkcja( string sciezka )
{
    ifstream plik;
    string wiersz;
    plik.open( sciezka.c_str() );
    int a;
    int i = 1;
    int suma = 0;
    while( !plik.eof() )
    {
        plik >> a;
        suma += a;
        if( czy( plik ) == false )
        {
            cout << "Napotkano blad w wierszu nr. " << i << endl;
            plik.clear();
            char b;
            plik >> b;
        }
        else if( czy( plik ) == true )
        {
            cout << suma << endl;
        }
        i++;
    }
    plik.close();
}
int main()
{
    funkcja( "C://Users//Mateusz//Documents//plik.txt" );
    return 0;
}
Wynik działania (albo raczej nie działania) programu:

Napotkano blad w wierszu nr. 1
Napotkano blad w wierszu nr. 3
Napotkano blad w wierszu nr. 4
Napotkano blad w wierszu nr. 6
Napotkano blad w wierszu nr. 7
Napotkano blad w wierszu nr. 8
Napotkano blad w wierszu nr. 10
Napotkano blad w wierszu nr. 11
Napotkano blad w wierszu nr. 12

Moim problemem jest to, że nie wiem do czego wykorzystać tą narzuconą z góry funkcję. Proszę o jakieś wskazówki/podpowiedzi.
P-112773
Jacob99
» 2014-06-26 12:01:23
Ile razy już było pisane na forum, żeby nie używać tej konstrukcji
while( !plik.eof() )
.
Zamiast niej powinno być
while( plik >> a )
I nigdzie w tej funkcji nie używasz
string wiersz;
P-112774
Mateus.
Temat założony przez niniejszego użytkownika
» 2014-06-26 12:16:40
Ja w kursie nie widziałem nigdy takiego warunku, a sam na  niego nie wpadłem. Tylko, że dalej nie wiem co zrobić z tą funkcją :(
P-112775
pekfos
» 2014-06-26 12:17:25
Ile razy już było pisane na forum, żeby nie używać tej konstrukcji
while( !plik.eof() )
.
Żeby jej nigdy nie używać? Ani razu. Nie licząc informacji powtarzanych bez zrozumienia.
P-112776
Mateus.
Temat założony przez niniejszego użytkownika
» 2014-06-26 12:26:14
string wiersz
 to pozostałość po jednej (przeoczyłem to) z poprzednich prób, gdzie używałem takiej pętli
while( getline( plik, wiersz ) ) { }
, ale tez nic mi z tego nie wyszło :( Czekam na jakieś porady :D
P-112777
pekfos
» 2014-06-26 12:39:09
C/C++
if( czy( plik ) == false )
{
    cout << "Napotkano blad w wierszu nr. " << i << endl;
    plik.clear();
    char b;
    plik >> b;
}
else if( czy( plik ) == true )
{
    cout << suma << endl;
}
i++;
Gdy czy() zwraca false, nie oznacza to błędu. Błąd musisz określić na podstawie stanu strumienia plik zaraz po operacji. Dodatkowo, drugi if jest niepotrzebny, wystarczy samo else. Wtedy nie będzie dodatkowego wywołania czy() które zepsuje wszystko. i musisz inkrementować raz na jedną linię, a nie wczytaną wartość. W tym samym miejscu musisz też wyzerować suma (po jej wypisaniu).
P-112779
Mateus.
Temat założony przez niniejszego użytkownika
» 2014-06-26 12:43:05
Ok. Dzięki za odpowiedź. Teraz muszę wyjść z domu. Dam znać po południu czy mi się udało :-)
P-112781
Mateus.
Temat założony przez niniejszego użytkownika
» 2014-06-26 16:42:57
Napisałem to wszystko (kilkakrotnie próbowałem) od nowa i przeanalizowałem tą funkcję
bool czy( ifstream & plik )
 i chociaż zrozumiałem (tak mi się wydaje) jej działanie, oraz do czego służy, to mój program działa tylko na dwa pierwsze wiersze pliku :(
Kod:
C/C++
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
bool czy( 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;
       
    }
}
void funkcja( string sciezka )
{
    ifstream plik;
    plik.open( sciezka.c_str() );
    float a;
    float i = 1;
    float suma;
    while( !plik.eof() )
    {
        suma = 0;
        while( czy( plik ) != true )
        {
            plik >> a;
            if( plik.fail() )
            {
                cout << "Bledne dane w wierszu nr. " << i << endl;
                plik.clear();
                char b;
                plik >> b;
                break;
            }
            else
            {
                suma += a;
            }
        }
        i++;
        cout << "Suma wynosi: " << suma << endl;
    }
}
int main()
{
    funkcja( "C://Users//Mateusz//Documents//plik.txt" );
    return 0;
}

Suma wynosi: 6
Bledne dane w wierszu nr. 2
Suma wynosi: 7
Suma wynosi: 5
Suma wynosi: 5
Suma wynosi: 13
Bledne dane w wierszu nr. 6
Suma wynosi: 0
Bledne dane w wierszu nr. 7
Suma wynosi: 7

Teraz to już nie wiem co robię źle (chociaż przypuszczam, że błąd jest w warunkach pętli).
Gdy zmieniam warunek w zewnętrznej pętli na
while( plik >> a )
 to otrzymuje takie cudo:
Suma wynosi: 5
Bledne dane w wierszu nr. 2
Suma wynosi: 4
Suma wynosi: 0
Suma wynosi: 2
Suma wynosi: 8
 Pomożecie? :D
P-112788
« 1 » 2 3
  Strona 1 z 3 Następna strona