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

[C++] Wyszukanie liczb w pliku tekstowym (zadanie domowe, rozdział 34)

Ostatnio zmodyfikowano 2015-02-20 23:40
Autor Wiadomość
jasiu
Temat założony przez niniejszego użytkownika
[C++] Wyszukanie liczb w pliku tekstowym (zadanie domowe, rozdział 34)
» 2015-02-20 19:35:17
Witam, to mój pierwszy post na tym forum to chciałbym na początek wszystkich pozdrowić i prosić o wyrozumiałość, zwłaszcza na początku..

Próbuje rozwiązać zadanie z wyszukaniem liczb w pliku tekstowym, w przypadku pierwszego kodu:
C/C++
#include <iostream>
#include <fstream>

using namespace std;

bool otworz_plik( ifstream & fPlik, string fSciezka )
{
    fPlik.open( fSciezka.c_str() );
    if( fPlik.good() )
         return true;
    else
         return false;
   
}

void zamknij_plik( ifstream & fPlik )
{
    fPlik.close();
}

void wyswietl_plik( ifstream & fPlik )
{
    string wers;
    while( getline( fPlik, wers ) )
         cout << wers << endl;
   
}

int suma_liczb_w_pliku( ifstream & fPlik )
{
    int liczba, suma = 0, licznik = 0;
   
    while( true )
    {
        fPlik.clear();
       
        fPlik >> liczba;
       
        if( fPlik.bad() )
             break;
       
        if( !fPlik.fail() )
        {
            cout << liczba << " ";
            suma += liczba;
            licznik++;
        }
       
        if( fPlik.eof() )
             break;
       
    }
   
    cout << endl << "Znaleziono " << licznik << " liczb";
   
    return suma;
}


int main()
{
    ifstream plik;
    string sciezka = "plik.txt";
   
    if( otworz_plik( plik, sciezka ) ) //Sprawdzanie poprawnosci otwarcia pliku
    {
        cout << "Plik zostal otwarty poprawnie" << endl;
        wyswietl_plik( plik );
    }
    else
         cout << "Nie udalo sie otworzyc pliku" << endl;
   
    //cout << suma_liczb_w_pliku(plik);                             // getline() spowodowalo ze plik sie skonczyl
    // CHYBA
    zamknij_plik( plik );
   
    if( otworz_plik( plik, sciezka ) ) // Ponowne otwarcie pliku
    {
        cout << " " << suma_liczb_w_pliku( plik );
        zamknij_plik( plik );
    }
   
    return 0;
}

program daje :


Plik zostal otwarty poprawnie
(...)
123

Wydaje mi się, że jest błąd w funkcji suma_liczb_w_pliku, po wczytaniu liczby 123 działanie programu nie kończy się, trwa w nieskończonej pętli. To już pozostawiam Wam. Moja druga próba rozwiązania zadania skupiła się na zmianie ww funkcji i wklejam tylko kod tej funkcji, reszta jest identyczna więc może akurat tam coś jest nie tak.

C/C++
int suma_liczb_w_pliku( ifstream & fPlik )
{
    int liczba, suma = 0, licznik = 0, pozycja = 0;
    char znak;
   
    while( true )
    {
        fPlik.clear();
        fPlik >> znak;
       
        if( fPlik.bad() )
             break;
       
        if( !isspace( znak ) && pozycja == 0 ) // Sprawdza czy plik zaczyna sie od liczby
        {
            fPlik.seekg( 0 ) >> liczba; // lub znaku bialego
            if( fPlik.bad() )
                 break;
           
        }
       
        if( !isspace( znak ) && pozycja != 0 )
        {
            fPlik >> liczba;
            if( fPlik.bad() )
                 break;
           
        }
       
        if( !fPlik.fail() )
        {
            cout << liczba << " ";
            suma += liczba;
            licznik++;
        }
        else
       
       
        if( fPlik.eof() )
             break;
       
        pozycja++;
    }
W tym przypadku program wyswietla :

Plik zostal otwarty poprawnie
123Wprowadzenie
(...)
123 1 196 12 68 24 10 68 4 20 6 202 0 377 5 1996 1995
Znaleziono 17 liczb 5107

W tym przypadku program kończy działanie i niby wszystko ok poza miejscami w tekście '12 368' , '10 368' , '4 420 606' bo z każdej liczby bezpośrednio za spacją ucina pierwszą cyfre. Dołączam również kod trzeciej mojej próby, która daje identyczny wynik.

C/C++
int suma_liczb_w_pliku( ifstream & fPlik )
{
    int liczba, suma = 0, licznik = 0, pozycja = 0, seekg;
    char znak;
   
    while( true )
    {
        fPlik.clear();
        seekg = fPlik.tellg();
        fPlik >> znak;
       
        if( fPlik.bad() )
             break;
       
        if( znak == 1 || znak == 2 || znak == 3 || znak == 4 || znak == 5 || znak == 6 || znak == 7 || znak == 8 || znak == 9 )
        {
            fPlik.seekg( seekg );
            fPlik >> liczba;
           
            if( fPlik.bad() )
                 break;
           
        }
       
        if( !isspace( znak ) && pozycja == 0 ) // Sprawdza czy plik zaczyna sie od liczby
        {
            fPlik.seekg( 0 ) >> liczba; // lub znaku bialego
            if( fPlik.bad() )
                 break;
           
        }
       
        if( !isspace( znak ) && pozycja != 0 )
        {
            fPlik >> liczba;
            if( fPlik.bad() )
                 break;
           
        }
       
       
        if( !fPlik.fail() )
        {
            cout << liczba << " ";
            suma += liczba;
            licznik++;
        }
        else
       
       
        if( fPlik.eof() )
             break;
       
        pozycja++;
    }

Przepraszam jeśli post jest za długi, mam nadzieję, że jest wystarczająco czytelny.
P-126901
DejaVu
» 2015-02-20 19:43:55
Czemu chcesz kończyć działanie programu jeżeli nie uda się wczytać liczby?
P-126903
jasiu
Temat założony przez niniejszego użytkownika
» 2015-02-20 19:58:08
Czy chodzi o
C/C++
if( fPlik.bad() )
     break;

? Jeśli tak to wydawało mi się, że .bad() występuje wtedy:
"Zwraca ona prawdę, jeżeli ostatnio wykonana operacja odczytu danych zakończy się niepowodzeniem z powodu wystąpienia błędu sprzętowego. Przez błąd sprzętowy należy rozumieć pojawienie się badsectorów na dysku, niedostępność urządzenia na którym znajdował się otwarty plik (np. pendrive lub dysk sieciowy) lub zabranie dostępu do pliku przez inny proces."
Zabezpieczam się przed tym, może warto było by dodać jakiś komunikat do użytkownika, nie traktuje tej metody do sprawdzenia czy wczytane dane są liczba czy znakiem bo do tego używam
.fail()
  a przynajmniej wydawało mi się, że tak trzeba..
P-126905
DejaVu
» 2015-02-20 23:07:14
Wybacz, moje niedopatrzenie. Nie pamiętam aż tak dobrze tych niuansów fstreama :)

C/C++
int suma_liczb_w_pliku( ifstream & fPlik )
{
    int liczba, suma = 0, licznik = 0;
   
    while( true )
    {
        fPlik.clear();
       
        fPlik >> liczba;
       
        if( fPlik.bad() )
             break;
       
        if( !fPlik.fail() )
        {
            cout << liczba << " ";
            suma += liczba;
            licznik++;
        } else
        {
            //!!!! TEGO CI BRAKOWAŁO !!!!
            fPlik.clear();
            char znak;
            fPlik >> znak;
            //!!!! TEGO CI BRAKOWAŁO !!!!
        }
       
        if( fPlik.eof() )
             break;
       
    }
   
    cout << endl << "Znaleziono " << licznik << " liczb";
   
    return suma;
}

Jeżeli wystąpił błąd wczytywania liczby z pliku to znaczy, że najbliższy znak nie jest cyfrą, czyli musisz go odczytać z pliku, aby przesunąć kursor kawałek dalej. Program Ci się zapętlał, bo próbowałeś odczytać liczbę cały czas z tego samego miejsca w pliku.

/edit:
Ale tak swoją drogą to widzę, że załapałeś podstawy programowania całkiem dobrze :)
P-126924
jasiu
Temat założony przez niniejszego użytkownika
» 2015-02-20 23:40:31
Dzięki, to rozwiązało problem :) Na pewno zapamiętam bo rozwiązanie okazuje się być proste (jak każde znane już rozwiązanie), a spędziłem przy tym wystarczająco dużo czasu, żeby utkwiło mi w pamięci..

Kiedyś w technikum miałem programowanie w Assemblerze, to dwie różne bajki ale może to mi pomaga teraz? :) temat do zamknięcia.
P-126930
« 1 »
  Strona 1 z 1