0

Issue is related only to Windows. I am using visual studio 2012 compiler (vc11).

I would like to read few lines (character by character) from input file (which is redirected as stdin). But after reading each line, I would like to fflush stdin.

Let me explain in details: I turn off stdin buffering by setvbuf function (without this stdin would be buffered and first flush clears the whole input). Then program reads few lines from input file. Characters are read one by one (fgetc function). After each line, I clear stdin with fflush. On Windows fflush on input stream is definied. According to MSDN: "If the stream is open for input, fflush clears the contents of the buffer. " https://msdn.microsoft.com/en-us/library/aa272686(v=vs.60).aspx

But I don't understand how it works. You can see that sometimes first character (of line) is not read from input. Probably due to fflush (maybe fflush clears this first character from stdin buffer?). But it happens only for few lines (some lines are read with first character).

Why does this first character disappear (sometimes)?

How can I correct this? (assuming that I would like to call fflush(stdin) after reading each line).

Program:

#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

int main()
{
    setvbuf(stdin, 0, _IONBF, 0);
    std::string text[6];
    for(int i = 0; i < 6; i++)
    {
        int input;
        char cc;
        do
        {
            input = fgetc(stdin);
            cc = (char)input;
            if (cc != '\n' && input != EOF)
            {
                text[i] += cc;
            }
        }
        while (cc != '\n' && input != EOF);
        fflush (stdin);
    }
    for(int i = 0; i < 6; i++)
    {
        std::cout <<text[i] << std::endl;
    }

    return 0;
}

Input file:

first
second
third
fourth
fifth
sixth

Execution command:

.\main.exe < input

Output (please note missing first character in few lines):

first
econd
hird
fourth
fifth
ixth
piotrp
  • 324
  • 2
  • 6
  • 1
    Don't tag for unrelated languages. C is not C++ is not C! – too honest for this site Jul 19 '16 at 16:08
  • `fgetc()` into a `char`, then testing whether the result is `EOF` is not a smart idea. – EOF Jul 19 '16 at 16:09
  • @Olaf I have the same issue in c and in c++. That is why I added two tags. But indeed, I posted only source code for c++. – piotrp Jul 19 '16 at 18:02
  • @EOF Thanks for notice. I missed this during preparing short example. Example corrected (of course it doesn't change main problem). – piotrp Jul 19 '16 at 18:04
  • `fflush(stdin)` is undefined behavior. See [this](http://stackoverflow.com/questions/2979209/using-fflushstdin/2979217#2979217). – DaBler Jul 19 '16 at 19:12
  • @DaBler fflush on input stream is undefined in standard, I agree. But Microsoft implementation defines how fflush works on input stream: "If the stream is open for input, fflush clears the contents of the buffer" (https://msdn.microsoft.com/en-us/library/aa272686(v=vs.60).aspx) – piotrp Jul 19 '16 at 19:40
  • 2
    Why do you feel like you need to `fflush(stdin)`? I can see maybe calling that _after_ the `for` loop, but not within it. In fact, I don't see the point of calling it at all. – GreatAndPowerfulOz Jul 19 '16 at 19:57
  • What are the return values of setvbuf and fflush? Also, the page you linked claims: _"fflush has no effect on an unbuffered stream."_ ... – Bob__ Jul 19 '16 at 20:24
  • @Bob__ setvbuf and fflush return 0 (success).You are right, they claim there is no effect. But on the other hand, if I remove fflush then all characters are read. So this fflush definitely has some effect. – piotrp Jul 19 '16 at 21:01
  • @Great.And.Powerful.Oz I think I won't need it in final solution. The story is the following: I would like to remove input lines from program memory (for example I want to hide it if someone make memory dump file). I started only with fflush without setvbuf. But it didn't work as fflush also cleared lines which has not been read yet (due to buffering). Now, I turn off buffering so probably I don't need this flush (as input line is not stored in input buffer). But I am still curious why this fflush works in such a way. – piotrp Jul 19 '16 at 21:18
  • Dunno why, seems like a bug. But it is clearly advancing the read cursor of the input buffer. – GreatAndPowerfulOz Jul 19 '16 at 21:21
  • `fflush` doesn't zero out the contents of the buffer, so it won't help. It isn't a security measure. – Harry Johnston Jul 19 '16 at 23:47
  • ... if you're worried about exposing the contents of the C runtime's buffer, I recommend that you use the Win32 API directly instead. – Harry Johnston Jul 19 '16 at 23:49
  • @HarryJohnston Thanks for suggestion. Do you think about any particular winapi function? I tried to find such possibility, but I found only FlushConsoleInputBuffer (it is again flush, so you probably thought about something else). – piotrp Jul 20 '16 at 09:45
  • I meant using ReadFile or ReadConsoleInput instead of fgetc. That way, the data is read directly from the console's buffer (which belongs to the operating system, and therefore isn't your problem) into a buffer you provide and can zero using SecureZeroMemory. That means that there is no intermediate buffer to worry about, like there is with the C runtime functions. – Harry Johnston Jul 20 '16 at 23:43

0 Answers0