Function name: scanf
Function: format the input.
Usage: int scanf (char * format [, argument,...]);
The scanf () function is a common terminal formatting input function that reads input information from the standard input device (keyboard. You can read any inherent type of data and automatically convert the value into an appropriate internal format.
The call format is scanf ("<formatted string>", <address Table> );
The scanf () function returns the number of successfully assigned data items. If an error occurs, EOF is returned.
Its control string consists of three types of characters:
1. Format the specifier;
2. Blank space character;
3. Non-blank characters;
(A) format the specifier
Format character description
% A reads a floating point value (valid only for C99)
% A Same as above
% C reads one character
% D read a decimal integer
% I reads decimal, octal, and hexadecimal integers
% O read an octal integer
% X reads hexadecimal integers
% X Same as above
% C reads one character
% S reads a string
% F reads a floating point number
% F same as above
% E same as above
% E same as above
% G same as above
% G same as above
% P reads a pointer
% U reads an unsigned decimal integer
% N number of equivalent characters that have been read to this point
% [] Scan character set combination
% Read % symbol
Additional format description
Modifier description
L/l length modifier input "long" data
H-length modifier input "short" data
W integer constant specifies the width of input data
* An asterisk is used to read data.
Hh, ll, same as h, l, but only valid for C99.
(B) white space characters
The blank character will slightly remove one or more blank characters in the reading operation of the scanf () function. The blank character can be space, tab, newline, and so on until the first non-blank character appears.
(C) non-blank characters
A non-blank character will cause the scanf () function to remove the same character as this non-blank character during reading.
The code is as follows: |
Copy code |
# Include <stdio. h> # Include <stdarg. h> # Include "loc_incl.h" Int scanf (const char * format ,...) { Va_list ap; Int retval; Va_start (ap, format ); Retval = _ doscan (stdin, format, ap ); Va_end (ap ); Return retval; } |
Macros defined in the stdarg. h header file, such as va_list, va_start, and va_end, have been introduced in the article (source code analysis of stdarg. h header file.
In the above code, we can see that there is a _ doscan function, which is defined in the header file loc_incl.h. The function declaration is as follows:
Int _ doscan (FILE * stream, const char * format, va_list ap );
The source code of the _ doscan function is as follows:
_ Doscan function code
In the source code above, it is worth noting that the getc macro of Line 1 is defined as follows:
# Define getc (p) (-- (p)-> _ count> = 0? (Int) (* (p)-> _ ptr ++ ):
_ Fillbuf (p ))
The call form of getc is ch = getc (fp). The function is to read a character from the file pointed to by the file pointer and return it to the int variable ch as a function value.
4th rows ~ Row 3 defines the variables to be used later.
23rd rows ~ Row 3 skips spaces in the format string and skips spaces in the input stream.
37th rows ~ Row 3: the input stream is consistent with the blank characters in the format string (space, tab, and newline).
44th rows ~ Row 3. If the character in format is '%', and the character in stream is '%', continue
54th rows ~ Row 3. The current format character is '*', indicating that the specified data type is read but not saved.
58th rows ~ Row 3: specifies 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 to the width
64th rows ~ Line 2: switch statement, used for format modifiers, including h, l, L, c, p, B, d, I, o, u ......, Also, the '[' modifier based on the scan set
The source code analysis of scanf functions requires a detailed understanding of the syntax format of scanf functions. The implementation of scanf functions is complex and requires careful consideration. Here is a preliminary analysis, the specifics need to be improved later.
Incorrect format input, for example
The code is as follows: |
Copy code |
# Include <stdio. h> Int main () { Int I; Do { Scanf ("% d", & I ); Switch (I) { Case 1: printf ("1n"); break; Case 2: printf ("2n"); break; Case 3: printf ("3n"); break; Default: printf ("Ostrap "); } } While (1) Return 0; } </Stdio> |
It seems that it is easy to enter an integer each time to judge the situation. We often focus on the results under the correct circumstances. But if we make a wrong input, will the results be the same as expected? I lost 1 first, and I have determined other correct situations. Then, enter. In this case, the program enters an endless loop and repeats output 1. Why?
I first made a breakpoint debugging and found that in the subsequent input, scanf did not assign the value of a to I, that is, the result of I was not overwritten. But why can I continue execution even if I have no input? This is definitely a problem with sacnf's operations on the buffer zone. If you know the problem, scanf still does not know how to handle the error. Later I checked it and explained it as follows:
1. For the correct input, scanf will continue to judge whether the subsequent input is in the correct format. If not, it will be filtered out. When it encounters a carriage return, it will end, and then the correct characters will be removed from the buffer zone, but do not press Enter.
2. The first format is incorrect. If you press enter, it will be removed from the buffer but discarded directly. If the format is invalid, scanf ends directly.
Therefore, for this problem, the buffer sequence is as follows: n a n, encounter n, take, continue, encounter a, scanf ends. From then on, it is blocked by this a, and an endless loop occurs.