1

I was thinking since the start that why can't fseek(stdin,0,SEEK_SET) and rewind(stdin) flush the input buffer since it is clearly written in cplusplusreference that calling these two functions flush the buffer(Input or Output irrespective).But since the whole idea seemed new,I had put it in a clumsy question yesterday.

Can fseek(stdin,1,SEEK_SET) or rewind(stdin) be used to flush the input buffer instead of non-portable fflush(stdin)?

And I was skeptical about the answers I got which seemed to suggest I couldn't do it.Frankly,I saw no reason why not.Today I tried it myself and it works!! I mean, to deal with the problem up the newline lurking in stdin while using multiple scanf() statments, it seems like I can use fseek(stdin,0,SEEK_SET) or rewind(stdin) inplace of the non-portable and UB fflush(stdin).

Please tell me if this is a correct approach without any risk.Till now, I had been using the following code to deal with newline in stdin: while((c = getchar()) != '\n' && c != EOF);. Here's my code below:

#include <stdio.h>

int main ()
{
    int a,b;
    char c;
    printf("Enter 2 integers\n");
    scanf("%d%d",&a,&b);
    printf("Enter a character\n");

    //rewind(stdin);   //Works if activated
    fseek(stdin,0,SEEK_SET);  //Works fine

    scanf("%c",&c);  //This scanf() is skipped without fseek() or rewind()
    printf("%d,%d,%c",a,b,c);

}

In my program, if I don't use either of fseek(stdin,0,SEEK_SET) or rewind(stdin),the second scanf() is skipped and newline is always taken up as the character.The problem is solved if I use fseek(stdin,0,SEEK_SET) or rewind(stdin).

Community
  • 1
  • 1
Jugni
  • 255
  • 5
  • 12

2 Answers2

1

I'm not sure where you read on cplusplusreference (whatever that is) that flushing to end of line is the mandated behaviour.

The closest matches I could find, http://www.cplusplus.com/reference/cstdio/fseek/ and http://www.cplusplus.com/reference/cstdio/rewind, don't mention flushing at all, other than in reference to fflush().

In any case, there's nothing in the C standard which mandates this behaviour either. C11 7.20.9.2 fseek and 7.20.9.5 rewind (which is, after all, identical to fseek with zero offset and SEEK_SET) also make no mention of flushing.

All they state is that the file pointer is moved to the relevant position in the stream.

So, to the extent this works in your environment, all we can say is that this works in your environment. It may not work elsewhere, it may even stop working in your envirnment at an indeterminate point in the future.


If you really want robust input, you should be using a two-stage approach, fgets to retrieve a line followed by sscanf to get what you want from that line. Mixing the two paradigms of input (scanf and getchar) is frequently problematic.

A good (robust, error-checking, and clearing to end of line if needed) input function can be found here.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Yes,that's written under `fflush()`.Since I have mentioned that paragraph in detail in my linked question,I didn't mention it here. – Jugni May 22 '13 at 06:20
  • Actually this is what that site says while discussing `fflush()`,indirectly but clearly stating that `fseek()` and `rewind()` **flush the buffer**. `In files open for update (i.e., open for both reading and writting), the stream shall be flushed after an output operation before performing an input operation. This can be done either by repositioning (fseek, fsetpos, rewind) or by calling explicitly fflush` – Jugni May 22 '13 at 06:22
  • @Jugni, then I think you may have misunderstood the reference. That fact that the `fseek` page has a link to the `fflush` page in _no way_ represents that `fseek` will flush. It's just a link to a related function. The text you refer to in your second comment above has to do with tied input/output streams such as stdin/stdout both attached to your terminal device. It states that trying to do an input op (getchar, fgets, etc) will first flush any outstanding output ops. – paxdiablo May 22 '13 at 06:22
  • No no,I don't conclude it from the link.I concluded from the paragraph I just quoted which indirectly,but clearly states that.I ran it on my program,and it seems to hold true!! – Jugni May 22 '13 at 06:23
  • The `fflush` page even states (my bold): In all other cases, the behavior depends on the specific library implementation. In **some** implementations, flushing a stream open for reading causes its input buffer to be cleared (but **this is not portable** expected behavior). – paxdiablo May 22 '13 at 06:26
  • But I have already stated that in my question,that `fflush(stdin)` is not portable!!I don't use it at all.But we are not talking about using `fflush()` to flush the input buffer,which is undefined.What we are discussing is that `fseeK()` and `rewind()`,when called,flush the I/O buffer.Nothing is said of **that** being **UB**!! – Jugni May 22 '13 at 06:28
  • They do _not_ (necessarily) flush the I/O buffer. There is _nothing_ is the standard that mandates such flushing. I've already explained about the tied streams which are what that quote refer to, which has nothing to do with fseek or rewind. It just means that, if you **output** "xyzzy" to stdout, it will be flushed before attempting input on stdin (assuming they refer to the same backing file). – paxdiablo May 22 '13 at 06:35
  • In other words, it's the printf/scanf combo doing that, not the fseek. The fseek _may_ flush the input buffer but, as stated, it's not mandated. – paxdiablo May 22 '13 at 06:36
  • @`it's the printf/scnaf combo doing that, not the fseek`---I am afraid it's not so!!Try it and the second `scanf()` is skipped.I see know reason why `printf()` will prevent that.The `fseek()` does that.Remove it and see the change. – Jugni May 22 '13 at 06:37
  • We've had this discussion. @paxdiablo, there's no point. He's not going to understand that "update" and "read" are two entirely different modes. He's not going to tell you what he means by "flush the buffer", because he doesn't even know what he means! – autistic May 22 '13 at 06:39
  • @Jugni, okay, let's try once more (last time). What gets flushed when doing input on a file is the previous _output_ for that file. That's what your quote states, nothing to do with seeking. Whether or not the _input_ stream is flushed on seek is not defined. The standard doesn't mention it, the quote you seem to think indirectly supports your contention is talking about something totally different. I can't make that any clearer, sorry. Just because something works in one environment, that does _not_ make it portable. Anecdotal evidence is NOT proof. – paxdiablo May 22 '13 at 06:41
  • @undefinedbehaviour But in the discussion you clearly stated it won't work!!You even stated `stdin` is not seekable.I would have accepted your argument(I had in fact!!) but it clearly doesn't gel with the results of my program above.`stdin` is clearly seekable and the `fseek()` and `rewind()` does cleanse the newline from the `stdin`.Which part of that did I fail to convey to you?The premise is simple---To deal with the newline that remains in the input buffer when we press **Enter**. – Jugni May 22 '13 at 06:41
  • @undefinedbehaviour And what with "update" and "read" being two different modes got to do with this?In both modes you can use `fseek()` and `rewind()`. – Jugni May 22 '13 at 06:43
  • @Jugni The fact that `stdin` is open for *read only* makes the paragraph you quoted entirely irrelevant; That paragraph doesn't apply to `stdin` because `stdin` isn't open for *update*. Do you understand? `stdin` is usually mapped to what's called an "interactive device". If you read about that in the C standard, you'll find "What constitutes an interactive device is implementation-defined." Do you understand how one implementation might treat `stdin` as seekable, while another might not? Rely upon *coincidence*, if you like, but that'll get you fails or fired one day... – autistic May 22 '13 at 06:51
  • @undefinedbehaviour But you didn't tell me all this yesterday,did you?How else was I supposed to know? – Jugni May 22 '13 at 06:52
  • @Jugni ... and by coincidence, I mean: Perhaps your implementation of C allows you to seek on stdin. Mine doesn't. That means your code doesn't work when compiling and running with my compiler, on my OS. Do you know what *unportable* means? How do you think that could affect your grade at college? **How arrogant must a student be to expect someone to *tell* him everything he needs to know?** Wow! Get a book. Learn to read... There's no reason you couldn't be reading the C standard, you know? – autistic May 22 '13 at 06:55
  • @undefinedbehaviour :-) You clearly misunderstood me.English is not my first language and I might have missed out some finer nuances.So bear with me as I never intended to be rude!! Thanks for the information you gave through your comments. – Jugni May 22 '13 at 06:57
-2

I tested it right ago, and I checked that fseek doesn't work on stdin. fseek() usually works on the file on the disk so that it seems to be prohibited to access to stdin by the kernel for some secure reasons. Anyway, it was so happy to see who thought like me. Tnx for good question.

  • Please, try to read this http://stackoverflow.com/about, to get more understanding about questions/answers here on SO. Your contribution is not answering the question. It is more a comment, which you can add once you'll increase your reputation: http://stackoverflow.com/faq#reputation – Radim Köhler Dec 14 '13 at 08:43