Some reposts about scanf

Source: Internet
Author: User

Reprinted from: http://blog.chinaunix.net/u3/99423/showart_2100968.html

I have made many mistakes in the scanf function, and I have also seen mistakes made by others. Remember to remind myself not to repeat the same mistakes. If it is useful to you, it will be better :) if you find any errors in the article, you are welcome to give your advice. Hope to study with everyone! (My mailbox: moongbingbing@gmail.com blog: http://blog.csdn.net/wayne92 Wen Ming) for a detailed scanf function interpretation, you can go to see the C programming language (K & C) and C language Daquan (I posted the scanf part later ).

Which of the following were the mistakes: (in xp SP2 and vc6.0 environments)
1. blank spaces
# Include <stdio. h>
Main ()
{
Int;
Printf ("input the data \ n ");
Scanf ("% d \ n", & a); // here there is an additional carriage return \ n
Printf ("% d", );
Return 0;
}
The result is ended by entering two programs, not the Expected One. Why?
Cause: When a blank character ends, scanf skips the blank character to read the next character, so you must enter another number. The blank spaces include spaces, tabs, line breaks, carriage returns, and page breaks. So if you use scanf ("% d", & a), the same problem will occur.
Solution: Most of these errors are incorrect input. Just pay more attention to them. This problem is not easy to check, compilation is not a problem, and a space is not easy to see. When the problem occurs in your program, you can check it by yourself.

2. Buffer Problems
This is a very easy mistake and I miss it many times.
# Include <stdio. h>
Main ()
{
Int n = 5;
Char c [n];
For (int I = 0; I <n; I ++)
C [I] = scanf ("% c", & c [I]);
Printf (c );
Return 0;
}
If you enter:
A
B
C
Then the loop will end "in advance.
Cause: After entering a and the first carriage return, a and the carriage return will remain in the buffer zone. The first scanf reads a, but there is a \ n in the input buffer, and the second scanf reads this \ n. Then enter B and the second carriage return. Similarly, the third scanf reads B and the fourth scanf reads the second carriage return. The fifth read is c. Therefore, all five scanf instances are executed, but they are not completed before submission. Some scanf only read the carriage return.
Solution: Change the program to this:
For (I = 0; I <n; I ++ ){
Scanf ("% c", & c [I]);
Fflush (stdin); // refresh the slow-forward zone
}
Or use the gets () function instead of scanf, for example:
# Include <stdio. h>
Main ()
{
Char c [5];
Gets (c );
Printf (c );
Return 0;
}
Note: This function automatically converts the carriage return you finally typed into the character '\ 0 '. If your input exceeds the size of the array, an error occurs.

3. The parameter input type of the scanf () function does not match
This is a problem I have seen on the csdn forum. This error is sometimes confusing.
# Include <stdio. h>
Main ()
{
Int a = 123;
Char c = 'T ';
Printf ("input \ n ");
Scanf ("% d % c", & a, & c );
Scanf ("% d % c", & a, & c );
Scanf ("% d % c", & a, & c );
Printf ("% d \ n % c \ n", a, c );
Return 0;
}
When you enter a and press enter, the following two scanf statements are skipped and the output is
123
T
Cause: For scanf ("% d % c", & a, & c), when the scanf statement is executed, first try to read a % d type data from the buffer, if it matches the first parameter, the system continues to read data from the buffer and matches the second parameter until all parameters are matched; if one of the parameters does not match, the system jumps out from this place, ignores all parameters after scanf, and executes the next statement.
You can use the following program to verify it:
# Include <stdio. h>
Int main ()
{
Int a = 123, B = 1;
Char c = 'T ';
Scanf ("% d", & a, & B );
Scanf ("% c", & c );
Printf ("% d \ n % c \ n", a, B, c );
Return 0;
} Input: 2 press enter a and press Enter.
The result is:
2
1
A
Solution: When the scanf () function is successfully executed, the returned value is the number of successfully read variables. That is to say, your scanf () function has several variables. If all the scanf () functions are read normally, it returns a few. However, you should pay attention to another problem. If illegal data is input, there may be residual information in the keyboard buffer.
For example:
# Include <stdio. h>
Main ()
{
Int a = 123, B;
While (scanf ("% d", & a, & B )! = 2)
Fflush (stdin );
Printf ("% d \ n", a, B );
Return 0;
}
You can give it a try. If the input is not a number, what will happen.

Supplement: Scanf is a rare but useful conversion character: [...] and [^...].
# Include <stdio. h>
Main ()
{
Char strings [100];
Scanf ("% [1234567890]", strings );
Printf ("% s", strings );
Return 0;
}
Run. Input 1234werew and the result is 1234.
It can be found through running that if the entered character belongs to a character in the character string in square brackets, the character is extracted; if it is not found, the extraction is completed. This method automatically adds a string terminator to the end of the extracted character.
Scanf ("% [^ 1234567890]", strings); it is used to end extraction if a character is found to belong to a character in the string within square brackets; extract this character if it does not. This method automatically adds a string terminator to the end of the extracted character.
Note: square brackets cannot contain spaces, for example, scanf ("% [1234567890]", strings); scanf ("% [^ 1234567890]", strings ); do not include spaces.
This method can also solve the problem that scanf input cannot contain spaces. Use
Scanf ("% [^ \ n]", strings. It's amazing.

Scanf prototype: See C language Daquan and K & C
# Include <stdio. h>;
Int scanf (const char * format ,...);
The scanf () function is a common subroutine used to read content from stdin, a standard input stream. It can read all inherent types of data and automatically convert the data into an internal form.
In C99, format is modified with restrict.
The control string pointed to by format is composed of the following three types of characters:
● Format specifiers
● Blank characters
● Non-blank characters

Conversion character (followed by %)
A read floating point value (C99 only)
A read floating point value (C99 only)
C read single character
D. Read the decimal integer.
I-read decimal, octal, and hexadecimal Integers
E read floating point number
E read floating point number
F Read floating point number
F Read floating point number (C99 only)
G read floating point number
G read floating point number
O eight bytes read
S read string
X-read hexadecimal number
X-read hexadecimal number
P read pointer Value
N The number of equivalent characters that have been read so far
Unsigned decimal integer read by u
[] Character Set Merging
% Read % (percent)

For example, % s indicates the read string and % d indicates the read integer. The processing sequence of the format string is from left to right, and the format specifiers match the variable in the variable table one by one. To read long integers, you can place l (ell) in front of the format specifier; To read short integers, you can place h in front of the format specifier. These modifiers can be used with code in d, I, o, u, and x formats.

By default, a, f, e, and g tell scanf () to allocate data to float. If l (ell) is placed before these modifiers, scanf () allocates data for double. The use of L tells scanf () that the variable for receiving data is a long double variable.

If the modern compiler program used supports the wide character feature added in 1995, it can be used together with the c format code to describe the wide character pointer of the type wchar_t with the l modifier; it can also be used together with the s format code to describe the wide string pointer with an l modifier. The l modifier can also be used to modify the scan set to indicate the width.

The blank character in the control string causes scanf () to skip one or more blank lines in the input stream. A blank space can be space, tab, and newline ). Essentially, the blank characters in the control string make scanf () read in the input stream, but do not save the results until non-blank characters are found.

A non-blank character allows scanf () to read a matched character in the stream and ignore it. For example, "% d, % d" causes scanf () to read an integer first, discard the comma in the reading, and then read another integer. If no matching is found, scanf () returns.

In scanf (), the variable used to save the read value must be a variable pointer, that is, the address of the corresponding variable.

In the input stream, data items must be separated by spaces, tabs, and new line characters. Comma and semicolon are not separators, such as the following code:
Scanf ("% d", & r, & c );
Input 10 20 will be accepted, but 10 or 20 will fail.

The asterisk (*) between the percent sign (%) and the formatted character indicates that the specified type of data is read but not saved. Therefore,
Scanf ("% d % * c % d", & x, & y );
In the 10/20 read operation, add the 10 variable x and 20 to the y variable.

The format command can indicate the maximum domain width. The integer between the percent sign (%) and the format code is used to limit the maximum number of characters read from the corresponding domain. For example, if you want to read no more than 20 characters into address, you can write it as follows:
Scanf ("% 20 s", address );

If the input stream contains more than 20 characters, the next scanf () is read from this stop. If a blank character has been encountered before reaching the maximum domain width, the read to this domain is immediately stopped. At this time, scanf () jumps to the next domain.

Although spaces, tabs, and new line characters are all used as domain-separated symbols, reading single-character operations are processed by general characters. For example, call the input stream "x y:
Scanf ("% c", & a, & B, & c );
After return, x is in variable a, space is in variable B, and y is in variable c.

Note that other characters in the control string, including spaces, tabs, and new line characters, are used to match and discard characters from the input stream. For example, if the input stream "10t20" is specified, call:
Scanf ("% dt % d", & x, & y );
Place 10 and 20 in x and y respectively, and t is abandoned because t is in the control string.

The ansi c standard adds a new feature to scanf () called scan set ). The scan set defines a character set combination that can be read by scanf () and assigned to the corresponding character array. A scan set is defined by a string of characters in square brackets. It must be prefixed with a percent sign before the left square brackets. For example, the following scan set causes scanf () to read characters A, B, and C:
% [ABC]

When using the scanning set, scanf () continuously eats the characters in the set and puts them in the corresponding character array until it finds that the characters are not in the Set (that is, the scanning set only reads matching characters ). When returned, the array contains a string ending with null and composed of read characters.

Character ^ can be used to describe the complement set. When the ^ character is placed as the first character of the scan set, it forms a complementary set of commands consisting of other characters, indicating that scanf () only accepts unspecified other characters.
For many implementations, a hyphen can be used to specify a range. For example, the following scan set allows scanf () to accept letters A to Z:
% [A-Z]
It is important to note that the scan set is case sensitive. Therefore, if you want to scan uppercase and lowercase characters, you must specify uppercase and lowercase letters respectively.
Scanf () returns the value equal to the number of successfully assigned fields, but reading unassigned fields due to the asterisk modifier is not included. If an error is returned before the first field is assigned a value, EOF is returned.

C99 adds several format modifiers for scanf (): hh, ll, j, z, and t. The hh modifier can be used for d, I, o, u, x, X, or n. It indicates that the corresponding variable is signed or unsigned char value, or when used for n, the corresponding variable is a pointer to the long char type variable. The ll modifier can also be used for d, I, o, u, x, X, or n. It indicates that the corresponding variable is the value of signed or unsigned long int.
The j format modifier is applied to d, I, o, u, x, X, or n, indicating that the matching variable is intmax_t or uintmax_t. These types are declared in <stdint. h>; and they indicate the integer of the maximum width.
The z-format modifier applies to d, I, o, u, x, X, or n, indicating that the matched variable is a pointer to a size_t object. This type is declared in <stddef. h>; and describes the structure of sizeof.
The t format modifier applies to d, I, o, u, x, X, or n, indicating that the matched variable is a pointer to a ptrdiff_t object. This type is declared in <stddef. h>; and the difference between the two pointers is described.

Example:

# Include <stdio. h>;
Int main (void)
{
Char str [80], str2 [80];
Int I;
/* Read a string and a integer */
Scanf ("% s % d", str, & I );
/* Read up to 79 chars into str */
Scanf ("% 79 s", str );
/* Skip the integer between the two strings */
Scanf ("% s % * d % s", str, str2 );
Return 0;
}

Let's take a look at why fflush is not used in linux:

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

Laiyuan: ant's C/C ++ standard programming Author: antigloss grade: Excellent
Published on February 22, 12809, reads (Font: large, medium, small]

The last modification of Antigloss is 2006-11-25.

 

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, 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);

 

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 isNot Defined.

The original article is as follows:


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 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.

/* 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 ,*/

/* Will remain\ NCharacter. */

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

Return 0;
}

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.