Home > database >  Does the scanf empty the buffer after reading the input data (in C)?
Does the scanf empty the buffer after reading the input data (in C)?

Time:05-06

#include <stdio.h>
#include <stdlib.h>

int main()
{
    char buf[1024];
    int a,b;
    int i;
    
    setbuf(stdin, buf);
    scanf("%d %d", &a, &b);
    
    for(i=0; buf[i]!='\n'; i  ){
        putchar(buf[i]);  
    }
    
    putchar('\n');

    return 0;
}

When I input the values 1 2, I used setbuf to find out if the buffer was really cleared after reading the values.
When I printed out the buf, however, the value I entered remained the same in buf. That is, the output was 1 2

Why is this happening?
I would really appreciate if you could answer.

CodePudding user response:

Collating what is found in the comments, there's no guarantee that the libc implementation will clear the stdin buffer. The FILE structure could just keep a pointer to its current position within the buffer.

In addition, you need to change the size of the buffer to BUFSIZ and make it so that its lifetime is for the rest of the program. According to the C11 standard:

The buffer has to have a lifetime at least as great as the open stream, so the stream should be closed before a buffer that has automatic storage duration is deallocated upon block exit.

This can be accomplished by either making the buffer global or declaring it to be static:

static char buf[BUFSIZ];

CodePudding user response:

Here is what the C Standard says about function setbuf():

7.21.5.5 The setbuf function

Synopsis

#include <stdio.h>
void setbuf(FILE * restrict stream,
            char * restrict buf);

Description

Except that it returns no value, the setbuf function is equivalent to the setvbuf function invoked with the values _IOFBF for mode and BUFSIZ for size, or (if buf is a null pointer), with the value _IONBF for mode.

Returns
The setbuf function returns no value.

7.21.5.6 The setvbuf function

Synopsis

#include <stdio.h>
int setvbuf(FILE * restrict stream,
            char * restrict buf,
            int mode, size_t size);

Description

The setvbuf function may be used only after the stream pointed to by stream has been associated with an open file and before any other operation (other than an unsuccessful call to setvbuf) is performed on the stream. The argument mode determines how stream will be buffered, as follows: _IOFBF causes input/output to be fully buffered; _IOLBF causes input/output to be line buffered; _IONBF causes input/output to be unbuffered. If buf is not a null pointer, the array it points to may be used instead of a buffer allocated by the setvbuf function277) and the argument size specifies the size of the array; otherwise, size may determine the size of a buffer allocated by the setvbuf function. The contents of the array at any time are indeterminate.

Returns

The setvbuf function returns zero on success, or nonzero if an invalid value is given for mode or if the request cannot be honored.


277) The buffer has to have a lifetime at least as great as the open stream, so the stream should be closed before a buffer that has automatic storage duration is deallocated upon block exit.

It follows that:

  • The array buf in your code should have a length of BUFSIZ
  • This array should not have automatic storage class because stdin is not closed before the function main returns. It should be defined as static char buf[BUFSIZ];
  • the buffer may or may not be used by the stream handling functions
  • The contents of the array at any time are indeterminate, hence nothing can be expected about the buffer contents: you observe that the user input is present, but this is not guaranteed. Most implementations have pointers or offsets in the FILE structure to keep track of used and available portions of the buffer.
  • It is highly unlikely that stream handling functions clear the buffer contents after reading the bytes, because it would prevent require reloading the buffer from the file in case of seeking back over previous contents, but again there is no guarantee about this either.

setbuf is a legacy function with limited use, setvbuf is preferred to select the buffering mode and buffer size.

  • Related