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

Niezrozumiałe działanie metody good() przy użyciu operatora >> (wczytywaine danych z pliku)

Ostatnio zmodyfikowano 2016-07-04 15:43
Autor Wiadomość
Szkaplerny
Temat założony przez niniejszego użytkownika
Niezrozumiałe działanie metody good() przy użyciu operatora >> (wczytywaine danych z pliku)
» 2016-07-04 00:43:40
Popełniłem taki oto kod:
C/C++
#include <string>
#include <fstream>
#include <iostream>
using namespace std;

void czytajPlik( ifstream & plik ) {
    int suma { };
    int liczba;
    while( true ) {
        if( plik.good() ) {
            plik >> liczba;
            cout << "Udalo sie wczytac liczbe: " << liczba << endl;
            suma += liczba;
        }
        else {
            cout << liczba << endl;
            break;
        }
    }
    cout << "Suma to: " << suma << endl;
}

int main()
{
    ifstream plik;
    plik.open( "C:\\Users\\TS\\Desktop\\Cpp\\cpp0x\\P4R33\\operatory\\operator\\liczby.txt" );
   
    czytajPlik( plik );
   
    plik.close();
   
    return 0;
}

I w takiej formie działa poprawnie. Nie rozumiem jednak, dlaczego wczytuje poprawnie wszystkie liczby.
Zmieniając formę w przy pętli while(true) na taką:
C/C++
while( true ) {
    plik >> liczba;
    if( plik.good() ) {
       
        cout << "Udalo sie wczytac liczbe: " << liczba << endl;
        suma += liczba;
    }
    else {
        cout << liczba << endl;
        break;
    }

Program nie czyta ostatniej liczby, jeżeli jest to ostatni(e) znak(i) w pliku. Czy mógłby ktoś wytłumaczyć działanie metody .good() w tym przypadku?
Starałem się przeanalizować zachowanie kompilatora krok po kroku, jednak wciąż to rozwiązanie do mnie nie przemawia.
P-149657
mateczek
» 2016-07-04 06:18:49
1. Stan strumienia sprawdzasz po wczytaniu liczby a nie przed. Formuła while(plik>>liczba) załatwia sprawę bo wczytuje liczbę i bada stan strumienia po wykonaniu funkcji
2. Nie ma sensu pracować na liczbie gdy nie udało się jej poprawnie wczytać, Bo sam nie wiem co wówczas jest w tej zmiennej(uwaga do twoich gałęzi else).

zobacz poniżej poprawiony kod.
C/C++
#include<iostream>
#include<fstream>
#include<string>
using namespace std;

void czytajPlik( string path ) {
    int suma = 0, liczba;
    ifstream plik( path );
    if( !plik ) { cout << "zła ścieżka do pliku"; return; }
    while( plik >> liczba ) {
        cout << "Udalo sie wczytac liczbe: " << liczba << endl;
        suma += liczba;
       
    }
    cout << "Suma to: " << suma << endl;
}

int main() {
    czytajPlik( "liczby.txt" );
    return 0;
}
P-149658
Szkaplerny
Temat założony przez niniejszego użytkownika
» 2016-07-04 10:16:32
Właśnie, w przykładzie drugim najpierw wczytuję liczbę do zmiennej liczba, a następnie sprawdzam poprawność wczytania. Pomimo tego taki zapis nie działa poprawnie. W pierwszym (działającym) najpierw sprawdzam poprawność, a dopiero potem wpisuje liczbę. Tego nie rozumiem.
Co do else - zapomniałem tego usunąć przed wstawieniem tutaj, chciałem zobaczyć co się wczytuje do zmiennej, gdy jest błąd. I wyświetla wtedy również ostatnią w pliku liczbę, i ona jest wczytywana do zmiennej jako goła liczba (bez newline etc). Chodzi mi o to, że ten drugi sposób wydaje się być poprawnym, a tak nie jest.
Pewnie i tak wykorzystam Twój sposób sprawdzania warunku w while, ale chodzi mi o czystą teorię, dlaczego to nie działa.
P-149661
carlosmay
» 2016-07-04 11:32:35
Pomimo tego taki zapis nie działa poprawnie.
Bo za ostatnią liczbą nie ma białego znaku, tylko znak końca pliku,
który ustawia strumień dla metody good() na false (uniemożliwia to czytanie poza plikiem).
Dodanie w pliku spacji bądź entera na koniec pliku naprawi ten "problem".

Używasz niepoprawnej kolejności działań.
P-149665
Szkaplerny
Temat założony przez niniejszego użytkownika
» 2016-07-04 12:21:25
O, dzięki wielkie! O to mi właśnie chodziło.
Czy w takim razie ten pierwszy (działający) kod ma jakieś luki pod względem tego warunku? Czy może dojść do sytuacji, gdzie jakaś liczba nie zostanie wczytana?
P-149667
carlosmay
» 2016-07-04 14:08:27
Czy w takim razie ten pierwszy (działający) kod ma jakieś luki pod względem tego warunku?
Ma luki. Punkt 2 @mateczek.

  • if sprawdza stan
  • podjęcie próby wczytania z pliku do zmiennej
  • niezależnie od powodzenia wykonywane jest działanie na zmiennej (której nie udało się wczytać)
Jeśli niepowodzenie ma miejsce w pierwszym cyklu pętli, zmienna ma wartość nieokreśloną.
W każdym kolejnym pozostaje niezmieniona z poprzedniego cyklu.

Rozwiązanie @mateczek jest najsensowniejsze.
P-149670
Szkaplerny
Temat założony przez niniejszego użytkownika
» 2016-07-04 15:43:15
I na takie też zmieniłem, dzięki wielkie za pomoc.
P-149673
« 1 »
  Strona 1 z 1