obsługa pliku - podwajanie ostatniej linii

0

Ktoś wyjaśni dlaczego mój program podwaja mi ostatnią linijkę z pliku tekstowego?

#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::string moj_string;
    std::ifstream obiekt_pliku;
    obiekt_pliku.open("mojedane.txt");
    while(obiekt_pliku.good())
    {
        obiekt_pliku >> moj_string;
        std::cout << moj_string << std::endl;
    }
    obiekt_pliku.close();
    return 0;
}

Z góry dziękuję za pomoc.

2

Bo obiekt_pliku.good() zwróci false dopiero jak spróbujesz czytać mając EOF. To znaczy że:

  • odczytasz ostatnią linię z pliku i będziesz na jego końcu
  • następnie obiekt_pliku.good() jeszcze jest true bo nie próbowałes czytać z EOFa
  • spróbujesz czytać z EOFa, nic nie wczytasz (dopiero teraz good() będzie false), ale masz nadal zapamiętaną starą wersję swojej zmiennej
  • wypiszesz tą starą wartość
  • przerwiesz pętlę do masz good() == false
0

Nadal nie rozumiem w 100%, ale mam nadzieję że będziesz miał do mnie cierpliwość ;)

mając EOF

kluczowe pytanie:
mając powiedzmy plik mojedane.txt:

pierwsza
druga
33333
444444
piata

w którym miejscu znajduje się EOF? Odpowiedź "na końcu pliku" mnie nie zadowala ponieważ:

program:

#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::cout << std::boolalpha;

    std::string moj_string;
    std::ifstream obiekt_pliku;
    obiekt_pliku.open("mojedane.txt");
    while(bool warunek = obiekt_pliku.good())
    {
        obiekt_pliku >> moj_string;
        //getline (obiekt_pliku, moj_string);
        std::cout << warunek
            << " " << moj_string << std::endl;
    }
    obiekt_pliku.close();
    return 0;
} 

Według mnie po skończeniu linii 5 - "piata" powinien przy następnym warunku obiekt_pliku.good() zwrócić false ponieważ według mnie zaraz po "piata" znajduje się EOF. Ale tak nie jest bo wynik programu to:

user@desktop-pc:~/Pulpit/matura-testowanie$ ./test
true pierwsza
true druga
true 33333
true 444444
true piata
true piata
user@desktop-pc:~/Pulpit/matura-testowanie$

Więc jak widać w 6 wywołaniu pętli while warunek jest spełniony czego nie rozumiem. (w 6 wywołaniu powinien czytać 6 linijkę pliku której nie ma więc tam musi być EOF)

ps:

  • następnie obiekt_pliku.good() jeszcze jest true bo nie próbowałes czytać z EOFa (tylko co próbowałem czytać? 6-tą linię której nie ma)
  • spróbujesz czytać z EOFa, nic nie wczytasz (dopiero teraz good() będzie false), ale masz nadal zapamiętaną starą wersję swojej zmiennej (i co z tego skoro najpierw jest sprawdzany warunek a później instrukcje, a nie na odwrót. Więc skoro będzie false to poniższe podpunkty nie powinny mieć miejsca)
  • wypiszesz tą starą wartość
  • przerwiesz pętlę do masz good() == false
1

Czy ja napisałem coś niewyraźnie? Załóżmy że jesteśmy w twoim przykładowym pliku na końcu czwartej linijki. Czytamy piątą i wypisujemy. Jesteśmy już co prawda na końcu pliku, ale nie próbowaliśmy jeszcze czytać z końca pliku więc plik jest cały czas good(). Wypisujemy więc piątą linijkę normalnie.
W następnym obiegu pętli wchodzimy do niej ponownie bo plik jest nadal good(). Dopiero teraz czytamy z EOFa i nic nie udaje nam się wczytać. Ale jesteśmy już w pętli więc znów wypisujemy zmienną, która ma wartość z poprzedniego obiegu pętli. Dopiero teraz pętla się przerywa bo plik ma good() == false

2
#include <iostream>
#include <fstream>
#include <string>
 
int main() {
    std::string moj_string;
    std::ifstream obiekt_pliku;
    obiekt_pliku.open("mojedane.txt");
    while(obiekt_pliku >> moj_string)
    {
        std::cout << moj_string << std::endl;
    }
    obiekt_pliku.close();
    return 0;
}
0

Dzięki za odpowiedź. Myślę że zrozumiałem:

Bo obiekt_pliku.good() zwróci false dopiero jak spróbujesz czytać mając EOF.

Po prostu myślałem że obiekt_pliku.good ustawia się na false już tutaj:

while(bool warunek = obiekt_pliku.good())

Ale jak napisałeś "dopiero jak spróbujesz czytać" więc obiekt_pliku.good() jest ustawiane na false w momencie czytania pliku czyli wykonywania instrukcji:

obiekt_pliku >> moj_string; 

Tak?

Ps. Ola Nordmann dzięki za nakierowanie, co zrobić aby czytało normalnie :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1