C/C ++ misunderstanding 2: fflush (stdin)

Source: Internet
Author: User
Tags rewind


1.Why?Fflush (stdin)If 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 entered integer, and prompt the user to enter an integer again, and then wait for the user to enter. 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, and this letter is left in the buffer again, so repeatedly, as a result, "Please input an integer: 2" is output continuously ". 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 must support this function (LinuxGccNot 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); IfIf the most recent operation executed by stream 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:PointOutput streamOrUpdate stream(Update stream), and the update stream

Int fflush (File*Stream);

If stream points to an output stream or an update stream in which
The most recent operation was not input, the fflush function causes
Any unwritten data for that stream 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 bufferAlthough the fflush (stdin) method cannot be used, we can write code to clearInput buffer. You only need to add a few simple codes after the scanf function.

/* C version */
# Include<Stdio. h> 
Int main (void)
{
Int I, C;
For (;;)
{
Fputs ("Please input an integer:", stdout );
Scanf ("% d", & I); If (feof (stdin) | ferror (stdin ))
{/* If the user inputsEnd mark(Or the file has beenRead),*/
/* Or occursRead/write errors, Then exit the loop */

/* Do something */
Break;
}
/* If no error occurs, clear the input stream. */
/* Use the while loopInput stream"Eat" the remaining data in */
While (C = getchar ())! = '/N' & C! = EOF );
/* UseScanf ("% * [^/n]");You can also clear the input stream. * // * The input stream remains unchanged./NCharacter. */Printf ("% d/N", I );
}

Return 0;
}

/* C ++ version */
# 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;
}

References: ISO/IEC 9899: 1999 (E) programming ages-C 7.19.5.2 the fflush FunctionThe C programming language 2nd edition by kernighan & ritchieiso/IEC 14882 () programming languages ages-C ++

Copyright of this ArticleC/C ++ standard programming for ant financialAnd the author antigloss. For details, please indicate the original author and source. Thank you.



Related Topics:No topics

Previous Article: C/C ++ misunderstanding 1: void main ()
Next article: C/C ++ misunderstanding 3: forced conversion of the return value of malloc ()

A total of 15 comments posted by netizens view all comments

Visitor: Missa
Rating: 3
The two methods mentioned later in the C-FREE4 all reported errors
The wrong one can implement the function. I don't know which compiler is used.
Visitor: antigloss
Score: 0
Sorry, I don't understand what you mean. What error is reported? Post it out
Visitor: Beginner C
Score: 0
I used the above Code into the DEV-C ++ compiler, the result is still not clear, the input character output is still the last integer, AND THE C version of stdout is what to do, do not understand, please explain. Thank you.
Visitor: antigloss
Score: 0
Yes? Paste your code to me.

It is to output please input an integer to the standard output (stdout). The default value is terminal (such as the screen ).

Visitor: Beginner C
Score: 0
I understand it wrong. Thank you for your tutorial. It is very good. The explanation is more detailed, so that you can understand it more comprehensively. I hope your subsequent updates will be faster, you have not talked about many things, such as enumeration, structure, file operations, and so on. It seems that you can add Assembly statements to C. There is also whether there can be a C ++ tutorial together, so there can be a comparison. It will be better.
Visitor: antigloss
Score: 0
I also want to update it quickly. The problem is that there is no time.

The nested assembly method in C varies with the compiler. For more information, see the instructions of the compiler.

There is no need to compare C and C ++.

Visitor: The owner is misleading!
Score: 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.

Visitor: antigloss
Score: 0
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 ))
{/* If the input stream is marked with an EOF tag */
Printf ("oh, no! EOF indicator is set now! /N ");
}
Clearerr (stdin);/* clear the EOF mark and error mark */
If (! Feof (stdin ))
{/* If the input stream is not marked with an EOF tag */
Printf ("OK! EOF indicator is unset now! /N ");
}
If (getchar () = EOF)
{/* If the data cannot be read from stdin */
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.

 

Related Article

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.