EOF , jak działa

0

Witam.

Korzystam z tejże książki https://helion.pl/ksiazki/jezyk-c-szkola-programowania-wydanie-vi-stephen-prata,cppri6.htm#format/d
Ogólnie to mi się podoba.Jestem aktualnie w rozdziale numer 5,zastanawia mnie jak działa EOF.Niestety nie rozumiem jak to działa i gdzie to mogę wykorzystać,w tej książce jest wiele przykładów lecz nie są jasno wytłumaczone,tak łopatologicznie,tylko są takie toporne te przykłady.Tak więc jak to działa,gdzie to wykorzystywać oraz z opłacalnością tego rozważania,jednym słowem wytłumaczcie mi łopatologicznie jak to działa i wykorzystywać w swoich projektach.

Dzięki

5

EOF to z angielskiego End Of File, czyli koniec pliku. Czyli np. mając do przeczytania pliku, czytasz od początku do EOF

0

Czyli powiedzmy że chcę odczytać zawartość np. dane.txt za pomocą fstream, to co biorę otwieram plik i tworzę pętle for( warunek eof) i wyświetlam zawartość na ekranie czy jak? To co zawsze przy otwieraniu pliku txt,exe itp muszę eof użyć tak?

3

Daj może konkretny kod, z którym masz problem (tylko nie za długi ;) ) - łatwiej się gada w oparciu o konkrety. Wspomniałeś w pierwszym poście, że doszedłeś do jakiegoś momentu w książce i się zablokowałeś. Pokaż ten program, prześledzimy jego działanie krok po kroku.

Ale co do zasady to z grubsza jest tak, jak piszesz - otwierasz jakiś plik i dajesz polecenie wczytania zawartości. Sprawdzasz, czy dostałeś EOF - jeśli tak, to znaczy, że dotarłeś do końca pliku. W przeciwnym razie masz pobrane w tym przebiegu dane, które musisz jakoś przetworzyć (np.wyrzucić na ekran), a następnie powtarzasz proces odczytu. I znowu - albo mamy koniec pliku, albo mamy dane. I tak w kółko.

2

Pętla for to nie najlepszy przykład, bo z założenia w for znasz liczbę powtórzeń. W tym przypadku wykonujesz pętlę której liczba iteracji nie jest znana, wykonujesz tak długo, aż dojdziesz do końca pliku czyli EOF.
Przykładów czytania plików jest tyle, że nie będę pisał kolejnego...

0

No nie stworzyłem/pracowałem na kodzie.W skrócie chcę zrozumieć jak to działa.Ten eof jest kluczowe w C++ czy niekoniecznie,są lepsze sposoby itp?

4

Jak pisał wyżej @cerrato, bez kodu ciężko nam coś powiedzieć. Nie czytałem tej książki, nie wiem co tam jest. Posłużę się innym przykładem: http://www.cplusplus.com/reference/ios/ios/eof/

#include <iostream>     // std::cout
#include <fstream>      // std::ifstream

int main () {

  std::ifstream is("example.txt");   // open file

  char c;
  while (is.get(c))
    std::cout << c;

  if (is.eof())                      //Mówimy tu o tej linii
    std::cout << "[EoF reached]\n";
  else
    std::cout << "[error reading]\n";

  is.close();

  return 0;
}

Wyjaśnienie krótkie
Przy odczytywaniu danych z pliku sprawdzamy czy to, co chcieliśmy zrobić, jest ok. Jeśli nie wiemy co jest w pliku i okazuje się, że same zera, to skądś musimy wiedzieć, że dotarliśmy do końca? A no funkcją eof.

Wyjaśnienie dłuższe na podstawie https://linux.die.net/man/2/read
Kiedy chcemy odczytać coś z pliku, tak naprawdę "prosimy" system o to, żeby dał nam dane. System wie jak dane rozłożone są na dysku (od tego jest system plików - teraz nas to nie interesuje). Powiedzmy, że mamy bardzo prosty wpis w systemie plików: nazwa pliku | rozmiar w bajtach | dane np.
plik.txt | 3 | 00000000 11111111 00000011
Pierwsze przejście pętli while (is.get(c)) odczyta 00000000 a wywołanie read zwraca 1
Drugie przejście pętli while (is.get(c)) odczyta 11111111 a wywołanie read zwraca 1
Trzecie przejście pętli while (is.get(c)) odczyta 00000011 a wywołanie read zwraca 1.
Za czwartym razem wywołanie systemowe zwróci -1 i trzeba sprawdzić co było przyczyną tego stanu. W tym przypadku EOF.

1

Kiedyś żeby zrozumieć choć trochę zasadę działania tego robiłem coś w tym stylu. To jest przykład pod Windows, czyli wciśnięcie CTRL + Z. Kompilujesz i uruchamiasz w cmd, i robisz według opisu z komentarzy w kodzie.

#include <stdio.h>

int main()
{
    int c;

    // pierwsza pętla będzie wykonywana gdy wciśniemy CTRL + Z i enter
    // ponieważ żeby kontynuwać program, tzn pętlę potrzeba zwrócić 
    // prawdę, a ten warunek przy wprowadzeniu CTRL + Z właśnie zwraca EOF
    // ale wprowadzenie dowolnego innego znaku spowoduje przerwanie pętli
    // Sprawdzany warunek, czyli wartośc c wynosi -1 tak samo EOF to -1
    // więc to jest równe, czyli warunek jest prawdziwy. Żeby przejść
    // do kolejnej pętli wpisz np 123 i wciśnij enter
    while ((c = getchar()) == EOF)
        printf("%d %d\n", c, EOF);

    // Tutaj CTRL + Z spowoduje przerwanie pętli ponieważ warunek zwraca 
    // nieprawdę. A pętla wykonuje się do póki warunek jest prawdziwy / spełniony.
    // Więc tutaj wpisywanie dowolnych znaków zachowa ciągłość programu,
    // ciągłość pętli. Założmy wprowadzisz teraz po uruchomieniu porogramu
    // w konsoliu najpierw CTRL + Z a potem dopiszesz np 123 wtedy 
    // wyjdzie z pętli. Ale jak napierw wpiszesz 123 a dopiero potem
    // CTRL + Z wtedy będzie kontynuowało wykonywanie pętli. Wtedy
    // wartośc c nie jest -1 tylko 26, co w http://www.asciitable.com/
    // oznacza znak '&'. Więc warunek wygląda tak 26 != -1 czyli nie jest
    // to równe, i do póki c nie będzie równe -1 warunek jest prawdziwy
    while ((c = getchar()) != EOF)
        printf("%d %d\n", c, EOF);

    return 0;
}
1

Define EOF Standard C ma główne dwa typy "do obsługi" EOF, a są nimi int oraz char.

EOF jest zdefiniowany jako -1, czyli 0xFFFFFFFF ze znakiem. O ile się nie mylę, to programiści najpopularniejszych systemów operacyjnych (OS), Unixo-podobnych i Windows nie zaimplementowali znaku kontrolnego o takiej, czy innej nazwie, który byłby po prostu jakimś bitem/bajtem, który poinformowałby odczyt/zapis, że tam właśnie jest koniec pliku (end of file). Ale są systemy operacyjne takie jak DOS, które to zaimplementowały. .txt file

Jak ten EOF wygląda. A no nie ma go "fizycznie" (mowa o najnowocześniejszych systemach, np. DOS ma taki znak na końcu pliku (przyjmijmy, że ten znak jest na końcu, bo czy faktycznie jest na końcu, czy nie to nie wiem)). Jest to struktura logiczna oparta o niskopoziomowe programowanie. Skoro na końcu każdego pliku nie ma czegoś jak EOF (mowa o modern OS) w takim razie jak to jest sprawdzane, czy jest koniec pliku, czy go nie ma. Odpowiedź można znaleźć na stronach typu wikipedia i nie tylko. Ewentualnie, samemu "zgadnąć" używając assembly x86-64 lub dojść do rozwiązania samemu, "wymyślić koło na nowo" i sprawdzić, czy nasze rozwiązanie nie jest tym, co jest już zaimplementowane w innych OS. Z tych trzech opcji wybrałem opcję pierwszą, czyli znalazłem odpowiedź w różnych dokumentacjach jedną z nich jest ta - chodzi o DOS. A poniżej objaśnię jak EOF jest sprawdzany w innych OS.

Having optained the file handle of the file, we can now use the file. For example read it. When you use interrupt 21h's file read function, you have to set up the registers as follows: AH = 3Fh BX = File handle CX = Number of bytes to read DX = Pointer to buffer to put file contents in Than you simply print out that buffer using interrupt 21h's print string function. However notice how you have to specify the amount of data to read. That's not good since most of the time we don't know how much data is in a file. So we can use a little trick. If an error occured, the error code is stored in AX. The error code 0 means that the program has encounter a EOF (End Of File). So we can simply make a while loop that prints a single byte from the text as long as AX is not equal to zero. If it is, we know that the file ended and we can terminate the program. Note that it is good coding practise to use interrupt 21h's function Close File to do just that. Here is the code for this thing:

Tłumacząc na polski, będzie to - podkreślony fragment, dot. DOS. Niemniej jednak dostrzeżesz jaką masz określoną liczbę danych do odczytania. To nie jest dobre, ponieważ większość czasu, nie będziemy wiedzieć jak wiele danych jest w pliku. Więc my możemy użyć małego triku. Jeśli wystąpił błąd, kod błędu jest przechowywany w AX. Kod błędu 0 oznacza, że program napotkał EOF (End Of File). Tak możemy prosto stworzyć pętlę while, która wypisze pojedynczy bajt z tekstu tak długo dopóki AX, który nie jest równy zero. Jeśli to jest, możemy wiedzieć, że plik jest skończony i możemy zakończyć program.

Reasumując. Jeśli np. odczyt napotka na błąd, czyli nie jest to zero, czyli jest jakimś znakiem z poza tej wartości do bufora zapisuje znak. Zero natomiast mówi o tym, że odczyt natrafił na EOF. Po stworzeniu pętli i po iteracjach dostaniemy jeden bajt za każdym obiegiem pętli w rejestrze AX - 16 bitowy, który nie jest zerem. Jeśli będzie zierem, to wtedy wiemy, że natrafiliśmy na koniec i pliku i możemy zakończyć proceder.

Zależnie od implementacji tego w języku niskopoziomowym jakim jest np. asm (chodzi o DOS), to gdy 16 bitów zostanie ustawionych na zero, wtedy jest EOF.|0000|0000|0000|0000| == 0x0000 DOS chyba liczy ten EOF jako dwa oddzielne bajty, czyli najpierw przeczyta 0x00 i później dla następnego bajtu 0x00, ale może się mylę. I jeśli te dwa bajty obok siebie są zerem to wtedy program przestaje odczytywać znaki, bo natrafił na tzw. EOF. Różne kodowania znaków w różnych OS sa tak napisane, że nie ma możliwości, żeby znak nie będący EOF (chyba że programista napisał niepoprawny kod, np. przypisał do złego typu) spowodował wyjście z odczytu pliku. Proszę nie wierzyć mi na słowo, że w DOS jest sprawdzane 16 bitów z zerem, tylko sprawdzić, bo sam nie jestem pewien, czy powołuję się na wiarygodne źródło, ale schemat w systemie typu DOS jest podobny, znak taki jest umieszczany na końcu pliku. Jeśli chodzi o ten przykład, to najprawdopodobniej int 21h powoduje, że rejestr AX dokonuje zmianę wartości na inną, więc jeśli po int 21h rejestr AX osiągnie wartość zero to wtedy jest zgłaszane EOF. Kończąc wypowiedź, EOF jest zgłaszane wtedy, gdy wystąpi dany zarezerwowany znak w pliku na końcu lub będzie jakaś sekwencja bajtów, która oznaczy ten end of file.

Error w powyższych zdaniach znaczy, jeśli nie został znaleziony znak końca pliku.

eof-distinguish

Ogólnie, to możesz skopiować sobie znak "" - tutaj do skopiowania i wkleić do pliku, następnie sprawdzić, że plik po napotkaniu znaku kontrolnego także przestanie dalej iterować znak po znaku.

Odpowiedź na pytanie znajduje się chociażby na wikipedii. Jest tam zdanie, które mówi, że Windows i Linux korzystają z rozmiaru pliku. Jeśli plik ma 64 bajty, to wiadomo, że po 64 bajcie nie ma nic, zwracane jest, więc taki wirtualny warunek (condition) o nazwie EOF.

1

(mowa o najnowocześniejszych systemach, np. DOS ma taki znak na końcu pliku (przyjmijmy, że ten znak jest na końcu, bo czy faktycznie jest na końcu, czy nie to nie wiem))

Co ty tak ciągle o tym DOS-ie ;-)
DOS nie ma tu nic do rzeczy i niczego nie zmienia. Rzeczywiście, teoretycznie, plik tekstowy (.txt) może mieć na końcu bajt 26, oznaczający koniec tekstu, i różne polecenia (jak type) mogą przerywać pracę znalazłszy taki bajt.
Nie chce mi się teraz sprawdzać czy type pod Windows 10 nadal traktuje bajt o wartości 26 jako koniec pliku, ale spodziewałbym się że tak.

W praktyce mało który plik tekstowy (nawet w czasach "dosowych") taki bajt na końcu miał. Koniec pliku to koniec pliku - OS wie ile bajtów ma plik to i wiadomo gdzie jest koniec i nie potrzeba tego oznaczać żadnymi dodatkowymi bajtami.

Bajty 0x00 nie są żadnym EOFem niezależnie od tego czy jest taki jeden, dwa, czy cztery.

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