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

Problemy ze zrozumieniem tellg()

Ostatnio zmodyfikowano 2018-02-09 11:40
Autor Wiadomość
Xardas666
Temat założony przez niniejszego użytkownika
Problemy ze zrozumieniem tellg()
» 2018-02-05 22:05:46
Wpisałem kod z przykładu z rozdziału 35. otwierając plik dane.txt o następującej treści:

1 2 3 4 5 3 2
5 2 2 1 3
3 4

i ku mojemu zdziwieniu wyskoczyło, że wczytano 3 znaki... Kod wygląda w ten sposób:
C/C++
#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    ifstream plik( "dane.txt" );
    if( !plik.good() )
         return 0;
   
    cout << "Na poczatku pozycja = " << plik.tellg() << endl;
    int iPozycjaStartowa = 4;
    plik.seekg( iPozycjaStartowa );
    cout << "Po ustawieniu pozycji pozycja = " << plik.tellg() << endl;
   
    int iLiczba;
    plik >> iLiczba;
    cout << "Po wczytaniu liczby pozycja = " << plik.tellg() << endl;
    cout << "WTF??!!" << endl;
   
    int iWczytanychZnakow = plik.tellg() - iPozycjaStartowa;
    cout << "\nLiczba: " << iLiczba << endl;
    cout << "Wczytano " << iWczytanychZnakow << " znakow" << endl;
    return 0;
}

Czy ktoś może mi wytłumaczyć, dlaczego po wczytaniu liczby tellg() wskazuje na pozycję przesuniętą o 3 w prawo, choć jeśli zapodam ponownie:
C/C++
plik >> iLiczba;
cout << "Po wczytaniu liczby pozycja = " << plik.tellg() << endl;
to wypisze mi prawidłowo następną liczbę znajdującą się o 2 miejsca w prawo, a nie 3?
O co tu chodzi?
P-169281
darko202
» 2018-02-07 11:29:54
plik.seekg( 10 ); //Ustawiasz pozycję odczytu danych od 11 znaku (pamiętaj, pozycje numeruje się od zera)

operator >> wczyta jeden ... z pliku

Pamiętaj, że operator >> zawsze pomija wszelkie napotkane białe znaki.

Białymi znakami są nazywane te symbole, które są używane w tekście i nie posiadają swojej reprezentacji graficznej. Przykładem takiego znaku jest spacja,

odpowiedz sobie na następujące pytania :
1. startujesz od ? znaku w pliku
2. wczytujesz >>  spację, znak, spację,
ile znaków jesteś dalej w pliku ? 


zapoznaj się z technika debugowania kodu
P-169306
Xardas666
Temat założony przez niniejszego użytkownika
» 2018-02-08 10:19:25
Dzięki za odpowiedź. Myślę, że rozumiem to, o czym piszesz. Wiem, że >> pomija białe znaki i wiem, że jest numerowane od zera. Mi chodzi o to, że tellg() za drugim razem wskazuje mi na inną pozycję, niż >> pobiera potem znak. Przykładowo za pierwszym razem tellg() wskazuje mi na 4. pozycję, bo tak ustawiłem przy pomocy seekg() i przy pomocy operatora >> dostaję znak czwarty. Tak więc zgodnie z tym przesuwa mnie o dwa znaki, skoro pierwszym z tych znaków odczytanych jest cyfra, drugim biały znak (spacja) i potem tellg() powinien wskazać na pozycję 6. (bo na 6. jest klejna cyfra), a wskazuje na 7. Jednak operator >> zastosowany ponownie wczytuje prawidłowo znak z pozycji 6. Tego nie rozumiem, a nie numerowania tablic czy ignorowania białych znaków przez operator >>. (Mam problem z tellg(), a nie z >>). Nie rozumiem, dlaczego tellg() wskazuje na innę pozycję, niż jestem w rzeczywistości.
P-169314
darko202
» 2018-02-08 14:24:46
moim zdaniem opisywany przez Ciebie problem wynika z Tego,

że nie rozumiesz działania operatora >>
wierzysz że >> pobiera jeden znak
a wystarczy sprawdzić gdzie faktycznie jesteś w pliku i co czyta >>

wykorzystaj przykład z
http://www.cplusplus.com​/reference/istream/istream/get/
pobranie jednego znaku get(c) + zwrócenie kodu pobranego znaku + zwrócenie pozycji tellg()

char a='A';
 printf("%d",(int)a);
 
i podobnie z >>

2.
zmień linię w plik np.
1 22 333 4444 ...
i sprawdź zachowanie >>  
+ zwrócenie pozycji tellg()
również bez używania seekg

P-169315
Xardas666
Temat założony przez niniejszego użytkownika
» 2018-02-09 11:40:04
Otóż jesteś w błędzie i w nic takiego nie wierzę ;) Źródło problemu znalazłem już wczoraj na jednym z forów. Cytuję:


tellg does not report the size of the file, nor the offset from the beginning in bytes. It reports a token value which can later be used to seek to the same place, and nothing more. (It's not even guaranteed that you can convert the type to an integral type.)

At least according to the language specification: in practice, on Unix systems, the value returned will be the offset in bytes from the beginning of the file, and under Windows, it will be the offset from the beginning of the file for files opened in binary mode. For Windows (and most non-Unix systems), in text mode, there is no direct and immediate mapping between what tellg returns and the number of bytes you must read to get to that position. Under Windows, all you can really count on is that the value will be no less than the number of bytes you have to read (and in most real cases, won't be too much greater, although it can be up to two times more).
(Źródło: tellg() function give wrong size of file? )

A jak wiadomo plik tekstowy nie jest plikiem binarnym.
Dziś zabrałem się za inny kurs (learncpp.com) i z ciekawości wyszukałem w Google na tej stronie informacji o tellg() i voila! Znalazłem rozwiązanie problemu, które po zaimplementowaniu zadziałało super w moim kodzie:


Note: Some compilers have buggy implementations of seekg() and tellg() when used in conjunction with text files (due to buffering). If your compiler is one of them (and you’ll know because your output will differ from the above), you can try opening the file in binary mode instead:
C/C++
ifstream inf( "Sample.dat", ifstream::binary );
(Źródło: 18.7 — Random file I/O)

Mimo wszystko dzięki za odpowiedź.

P.S. Wydaje mi się, że admin powinien to poprawić w swoim kursie.
P-169347
« 1 »
  Strona 1 z 1