srbcheema1
srbcheema1

Reputation: 610

Seekg not behaving as expected

    #include <string>
    #include <iostream>

    int main() {
        std::string str;
        char magic[9];
        std::cin.read((char *)magic, sizeof(magic));
        std::cin.seekg(0, std::ios::beg);

        while (std::cin >> str) {
            std::cout << str << std::endl;
        }
    }

my code contains implementation of seekg(0) fucntion on std::cin it is not behaving as expected on some of the files when run as ./a.out < filename

those files that it is not behaving as expected have property that they have number of characters(including endline characters and other white spaces) less than 9(9 is the number of characters we read from cin before seekg)

if the file contains more than 9 characters it is behaving as expected for example:

123456789

will give output as

123456789

while file containing less than 9 characters will not give output

for example:

1234

will give no output

Upvotes: 0

Views: 169

Answers (1)

paxdiablo
paxdiablo

Reputation: 881113

With a file of less than nine characters, you have already attempted to read past the end with your initial read. That means the eof (end of file) and fail flags have been set for the stream and, while seekg may reset eof, it does not reset fail (a).

You can check that by inserting:

cout << "eof/fail=" << cin.eof() << '/' << cin.fail() << '\n';

immediately before and after the seekg. For file sizes of 8, 9, and 10 respectively, you get:

eof/fail=1/1
eof/fail=0/1

eof/fail=0/0
eof/fail=0/0
12345678

eof/fail=0/0
eof/fail=0/0
123456789

You can see the first failure results in no output because the fail bit is still set. The second and third have output because it was never set (the output is the characters shown plus one newline).

To repair this, you can clear the fail bit simply by inserting the following before your seekg:

std::cin.clear();

Then running that code on the eight-character file gives:

eof/fail=1/1
eof/fail=0/0
1234567

showing that the clear has indeed cleared the fail bit.


You might also want to keep in mind that it's not a requirement for a stream to be seekable, especially if it's just coming in via standard input. You may find for certain sized files that you cannot seek back an arbitrary amount if you've read through a large chunk of the stream.


(a) For the language lawyers amongst us, Unformatted input functions (C++11 27.7.2.3/41, C++14 27.7.2.3/41 and C++17 30.7.4.3/41) all have essentially the same text on how seekg works (my emphasis):

After constructing a sentry object, if fail() != true, executes ...

Upvotes: 3

Related Questions