For more information, see fflush, buffer zone, scanf, and EOF.

Source: Internet
Author: User
Tags rewind

1.Why?Fflush (stdin)Yes

First, check the following program:

 

# Include<Stdio. h>

 

Int main (void)

{

Int I;

For (;;){

Fputs ("Please input an integer:", stdout );

Scanf ("% d", & I );

Printf ("% d \ n", I );

}

Return 0;

}

 

This program will first prompt the user to enter an integer, and then wait for the user to input. If the user inputs an integer, the program will output the integer just entered and prompt the user to enter an integer again, then wait for user input. However, once the user does not enter an integer (such as a decimal or letter), assumeScanfIf the last integer obtained by the function is 2, the program will continuously output "Please input an integer:
2 ". This is becauseScanf ("% d", & I );Only integers are allowed. If you enter a letter, the letter will be left in"Input buffer. BecauseBufferThere is data, soScanfThe function will not wait for user input, but read it directly in the buffer, but it is a letter in the buffer. This letter is left in the buffer again and again, so that the "please" is output continuously.
Input an integer: 2 ".

 

Someone may say, "this is the case. Add 'fflush (Stdin); ', SetInput bufferJust clear it ?" However, this is wrong!CAndC ++OfStandardFflush (stdin) has never been defined in ). Some people may say, "but I used fflush (stdin) to solve this problem. How can you say it is wrong ?" Indeed,SomeCompiler (suchVc6) Supports the use of fflush (stdin) to clear the input buffer, but not all compilers need to support this function (Linux
UnderGccNot Supported), because fflush (stdin) is not defined in the standard ).MsdnThe document also clearly states that fflush on input stream isExtensionTo
The C standard (fflush operation input stream is standard for CExpansion). Of course, if you don't care about the programPortability, Fflush (stdin) is no big problem. Below isC99PairFflushFunction Definition:

 

Int fflush (File*Stream);

 

IfStreamPointOutput streamOrUpdate stream(Update stream), and the update stream
If the most recent operation is not input, the fflush function transfers any data to be written in the stream
Host environment writes data to a file. Otherwise, its behavior isUndefined.

The original article is as follows:




Fflush (File*Stream);

If stream points to an output stream or an update stream in which
The most recentoperation was not input, the fflush function causes
Any unwritten data for thatstream to be delivered to the host environment
To be written to the file; otherwise, the behavior is undefined.

 

The host environment can be understood as the operating system or kernel.

 

From this we can see that if stream points to the input stream (such as stdin), then the behavior of the fflush function is uncertain. ThereforeFflush (stdin)Is incorrect, at least YesPoor portability.

 

 

2.ClearInput bufferMethod

 

Although fflush (stdin) cannot be used, we can write code to clear it.Input buffer. You only need to add a few simple codes after the scanf function.


# Include<Stdio. h>


Int main (void)
{
Int I, C;
For (;;)
{
Fputs ("Please input an integer:", stdout );
Scanf ("% d", & I );

If (feof (stdin) | ferror (stdin ))
{



Break;
}


While (C = getchar ())! = '\ N' & C! = EOF );

Printf ("% d \ n", I );
}

Return 0;
}


# Include<Iostream>
# Include<Limits>// To use numeric_limits

Using STD: cout;
Using STD: Endl;
Using STD: CIN;
Using STD: numeric_limits;
Using STD: streamsize;

Int main ()
{
Int value;
For (;;)
{
Cout <"enter an integer :";
Cin> value;
If (CIN. EOF () | cin. Bad ())
{// If the user inputsEnd mark(Or the file has beenRead),
// Or occursRead/write errorsTo exit the loop.

// Do something
Break;
}
// When an invalid character is read, the input stream will be inError status,
// To continue obtaining input, call the clear function first.
// ComeClear error mark of input streamBefore calling
// Ignore function to clear data in the input stream.
Cin. Clear ();
// Numeric_limits<Streamsize>: Max () returns the size of the input buffer.
// The ignore function clears the data in the input stream.
// You can query the specific usage of these two functions by yourself.
Cin. Ignore (numeric_limits<Streamsize>: Max (), '\ n ');

Cout <value <'\ n ';
}

Return 0;
}

 

 

This is what I saw in other forums! The author's opinion is incorrect! Misleading !!

1. Why is fflush (stdin) incorrect?
-----------------------------------------
Fflush (stdin) has never been defined in the C and C ++ standards ).
---------------------------------------------
Error. It cannot be said that fflush (stdin) is wrong. The author lists the standard content, which shows that the author has read the standard but has a wrong understanding of the standard content. The standard indicates that the results of fflush for input streams are undefined, but undefined is not equal to an error! At the same time, the standards of C and C ++ are not never defined as fflush (stdin). On the contrary, the standards say that the results of fflush used for input streams are undefined and are actually fflush (stdin) definition! Is the provision of fflush (stdin! However, the result is undefined!

The conclusion should be: the use of fflush (stdin) will produce portability problems, is a bad style code, but not a mistake.

Solution proposed by the author:

If (scanf ("% d", & I )! = EOF ){
While (C = getchar ())! = '\ N' & C! = EOF ){
;
}
}

The problem is not completely solved, and a major vulnerability exists. The main problem is that using getchar () does not clear the EOF flag. If you use a tc2.0, tc2.01, tc3.0, tc3.1, and other compilers to run the above Code, use Ctrl + Z to end the input or directly enter Ctrl + Z, the program will certainly enter an endless loop!

The reason is that the getchar () method does not clear the EOF flag. The EOF flag I mentioned here does not refer to the EOF returned by the function, it refers to the EOF sign generated internally when I/O functions encounter EOF.

We recommend that you use the rewind (stdin) method. Rewind not only clears the content in stdin, but also clears the EOF mark, and uses the following statement:

Scanf ("% d", & I );
Rewind (stdin );

In place of the above if statement, no matter how you enter Ctrl + Z, it will not go into an endless loop, and it is much simpler. It is a perfect solution.

 

 

 

First of all, thank you for your comment. It prompted me to review my article and correct some mistakes in the article. In particular, if two programs in the text are redirected to a file, an endless loop will occur. Now I have fixed this problem. Even if stdin is redirected to a file, there will be no endless loops. If there are other shortcomings in this article, please note that I am not grateful!

Then, I disagree with some of my opinions on the upstairs. I would like to express some comments here.

1. According to the upstairs definition of errors, I say that fflush (stdin) is wrong. However, everyone has different understandings of errors. I think this is an error if a function can be implemented with standard code without or without it, but relies on Compiler/system-specific function implementation. Of course, this is just my opinion. Also, I think using Compiler/system-specific functions (such as fflush (stdin);) is not a bad style code. In my opinion, bad style refers to a lot of code stacked together, not seriously indented, lack of comments, unclear code layers, and the Division of functional modules. In addition, I am very impressed with the opinion that "fflush is not defined as the result of using fflush for input streams. It is a definition of fflush (stdin. I think this is a unique and novel insight. The brains on the upstairs are really good! I never thought about this. Sorry!

2. My solution does have problems. Thank you for pointing out. But the problem is not what you said, but redirection. If stdin is redirected to a file, my original program will indeed lead to an endless loop.

The upstairs said, "when entering the end with Ctrl + Z or directly entering Ctrl + Z, the program will certainly enter an endless loop !", I tested it with TC, and entering Ctrl + z directly won't be an endless loop. However, After inputting some data, an endless loop does occur after entering Ctrl + Z. However, this is a TC problem! See the following code:

# Include <stdio. h>

Int main (void)
{
Int ch;

While (getchar ()! = EOF );
If (feof (stdin ))
{
Printf ("oh, no! EOF indicator is set now! \ N ");
}
Clearerr (stdin );
If (! Feof (stdin ))
{
Printf ("OK! EOF indicator is unset now! \ N ");
}
If (getchar () = EOF)
{
Printf ("but why still cannot read from stdin? \ N ");
}

Return 0;
}

Enter 21312313 ^ Z when compiling and running with TC. The result is as follows:

21312313 ^ Z
Oh, no! EOF indicator is set now!
OK! EOF indicator is unset now!
But why still cannot read from stdin?

Therefore, even if the EOF tag is not marked, data cannot be read from stdin if the input ends with ^ Z! This is a TC problem! The reason why my original program will have an endless loop when the input ends with ^ Z is that it cannot read data from stdin! Rewind (stdin) is used upstairs; then data can be read from stdin. It seems to be a specific TC function!

But thanks to the upstairs, I found that if stdin is redirected to a file, my program will have an endless loop. However, I wrote these two programs only to demonstrate how to clear stdin. I didn't think too much about other factors.

3. I strongly disagree with the solution proposed above! The solution proposed above is better than using fflush (stdin). It uses compiler-specific functions.

First, let's take a look at the standard definition of the rewind function:

Void rewind (File * stream );

The rewind function sets the file location tag of the stream to a file.
Start. If you do not consider it, it will clear the error mark of the stream, then the rewind Function
Equivalent

(Void) fseek (stream, 0l, seek_set );

The original article is as follows:

The rewind function sets the file position indicator
The stream pointed to by stream to the beginning of
File. It is equivalent

(Void) fseek (stream, 0l, seek_set)

Could t that the error indicator for the stream is also
Cleared.

K & R's C programming language, Second Edition simply says

Rewind (FP); equivalent to fseek (FP, 0l, seek_set); clearerr (FP );

It can be seen that the standard only means that rewind can set the file location mark of the stream to start the file, and clear the error mark of the stream, but does not define rewind (stdin) to clear stdin content, therefore, using rewind (stdin) may not clear stdin. In addition, if stdin is redirected to a file, using rewind will produce very "interesting" results. If you are interested, try it.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.