Items in this page:
In the previous practice you already learned how to use the printf() function to write/display/print/output character/string/text on your screen/terminal/standard output. In this lab you will learn another function, scanf() or a new secure version scanf_s(), on how to accept input from your standard input such as keyboard or user.
Create a new empty Win32 Console Application project named myscanf and add a C++ source file named myscanfsrc to the project. Make sure you set your project property to be compiled as C codes.
Type the following source code.
|
Build, run the program and show the output.
In this example the program use scanf() function to accept input from user. The program reads data from user and stores it somewhere in the memory (denoted by the hex addresses), then writes it on the standard output. Opposite to the printf() write formatted data to the standard output, scanf() read formatted data from the standard input, the keyboard.
The definition of the scanf() family is listed in the following Table.
Item | Description |
Function | scanf() family. |
Use | Read formatted data from the standard input stream. These functions are deprecated and it is better to use a more secure versions scanf_s(),_scanf_s_l(),wscanf_s(),_wscanf_s_l(). |
Prototype |
|
Parameters | format - Format control string. argument - Optional arguments. locale - The locale to use. |
Example | scanf("%64s", Name); |
Return value | Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of0 indicates that no fields were assigned. If format is a NULL pointer, the invalid parameter handler is invoked. If execution is allowed to continue, these functions return EOF and set errno to EINVAL. |
Include file | <stdio.h> or <wchar.h> for wscanf(),_wscanf_l() |
Remark | The scanf() function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. If copying takes place between strings that overlap, the behavior is undefined. When reading a string with scanf(), always specify a width for the %s format (for example, "%32s" instead of "%s"); otherwise, improperly formatted input can easily cause a buffer overrun. Alternately, consider using the secure version scanf_s(),_scanf_s_l(),wscanf_s(),_wscanf_s_l() or fgets(). wscanf() is a wide-character version of scanf(); the format argument to wscanf() is a wide-character string. wscanf() and scanf() behave identically if the stream is opened in ANSI mode. scanf() doesn't currently support input from a UNICODE stream. The versions of these functions with the _l suffix are identical except that they use thelocale parameter passed in instead of the current thread locale. |
Table 1 |
The information here applies to the entirescanf() family of functions, including the secure versions and describes the symbols used to tell the scanf() functions how to parse the input stream, such as the input stream stdin (standard input) forscanf(), into values that are inserted into program variables. A format specification has the following form:
%[*] [width] [{h | l | ll | I64 | L}]type
The format argument specifies the interpretation of the input and can contain one or more of the following:
Input | Description |
White-space characters | Blank (' '); tab ('\t'); or newline ('\n').A white-space character causes scanf()to read, but not store,all consecutive white-space characters in the input up to the next non–white-space character. One white-space character in the format matches any number (including 0) and combination of white-space characters in the input. |
Non-white-space characters | Except for the percent sign (%). A non–white-space character causes scanf() to read, but not store, a matching non–white-space character. If the next character in the input stream does not match, scanf() terminates. |
Format specifications | Introduced by the percent sign (%). A format specification causes scanf() to read and convert characters in the input into values of a specified type. The value is assigned to an argument in the argument list. |
Table 2. |
The format is read from left to right. Characters outside format specifications are expected to match the sequence of characters in the input stream; the matching characters in the input stream are scanned but not stored. If a character in the input stream conflicts with the format specification, scanf terminates, and the character is left in the input stream as if it had not been read.
When the first format specification is encountered, the value of the first input field is converted according to this specification and stored in the location that is specified by the first argument. The second format specification causes the second input field to be converted and stored in the second argument, and so on through the end of the format string.
An input field is defined as all characters up to the first white-space character (space, tab, or newline), or up to the first character that cannot be converted according to the format specification, or until the field width (if specified) is reached. If there are too many arguments for the given specifications, the extra arguments are evaluated but ignored. The results are unpredictable if there are not enough arguments for the format specification.
Each field of the format specification is a single character or a number signifying a particular format option. The type character, which appears after the last optional format field, determines whether the input field is interpreted as a character, a string, or a number.
The simplest format specification contains only the percent sign and a type character (for example, %s). If a percent sign (%) is followed by a character that has no meaning as a format-control character, that character and the following characters (up to the next percent sign) are treated as an ordinary sequence of characters, that is, a sequence of characters that must match the input. For example, to specify that a percent-sign character is to be input, use %%.
An asterisk (*) following the percent sign suppresses assignment of the next input field, which is interpreted as a field of the specified type. The field is scanned but not stored. For example scanf_s("%d", x, 20) where 20 byte reserved for the x.
The secure versions (those with the _s suffix) of the scanf() family of functions require that a buffer size parameter be passed preceding each parameter of type c,C,s,S or [.
These functions normally assume the input stream is divided into a sequence of tokens. Tokens are separated by whitespace (space, tab, or newline), or in the case of numerical types, by the natural end of a numerical data type as indicated by the first character that cannot be converted into numerical text. However, the width specification may be used to cause parsing of the input to stop before the natural end of a token.
The width specification
The Width Field
|
char str[21];
scanf("%20s", str, 21);
If the width field is not used, scanf() will attempt to read the entire token into the string. If the size specified is not large enough to hold the entire token, nothing will be written to the destination string. If the width field is specified, then the first width characters in the token will be written to the destination string along with the null terminator.
The optional prefixes h,l,ll,I64, and L indicate the size of the argument (long or short, single-byte character or wide character, depending upon the type character that they modify). These format-specification characters are used with type characters in scanf() or wscanf() functions to specify interpretation of arguments as shown in the following table. The type prefix I64 is a Microsoft extension and is not ANSI/ISO compatible. The type characters and their meanings are described in the "Type Characters for scanf() functions" table in scanf() Type Field Characters.The h,l, and L prefixes are Microsoft extensions when used with data of type char. You might not find it in other C/C++ compilers.
The size prefixes for scanf() and wscanf() are listed in the following Table.
To specify | Use prefix | With type specifier |
double | l (el letter) | e, E, f, g, or G |
long double (same as double) | L | e, E, f, g, or G |
long int | l | d, i, o, x, or X |
long unsigned int | l | u |
long long | ll | d, i, o, x, or X |
short int | h | d, i, o, x, or X |
short unsigned int | h | u |
__int64 | I64 | d, i, o, u, x, or X |
Single-byte character with scanf() | h | c or C |
Single-byte character with wscanf() | h | c or C |
Wide character with scanf() | l | c or C |
Wide character with wscanf() | l | c, or C |
Single-byte – character string withscanf() | h | s or S |
Single-byte – character string withwscanf() | h | s or S |
Wide-character string with scanf() | l | s or S |
Wide-character string with wscanf() | l | s or S |
Table 3. |
The following examples use h and l with scanf_s() functions and wscanf_s() functions:
scanf_s("%ls", &x, 2); // read a wide-character string
wscanf_s("%hC", &x, 2); // read a single-byte character
If using an unsecured function in the scanf() family, omit the size parameter indicating the buffer length of the preceding argument.
To read strings not delimited by whitespace characters, a set of characters in brackets ([ ]) can be substituted for the s (string) type character. The set of characters in brackets is referred to as a control string. The corresponding input field is read up to the first character that does not appear in the control string. If the first character in the set is a caret (^), the effect is reversed: The input field is read up to the first character that does appear in the rest of the character set.
Note that %[a-z] and %[z-a] are interpreted as equivalent to %[abcde...z]. This is a common scanf() function extension, but note that the ANSI standard does not require it.
To store a string without storing a terminating null character ('\0'), use the specification %nc where n is a decimal integer. In this case, the c type character indicates that the argument is a pointer to a character array. The next n characters are read from the input stream into the specified location, and no null character ('\0') is appended. If n is not specified, its default value is 1.
The type character is the only required format field; it appears after any optional format fields. The type character determines whether the associated argument is interpreted as a character, string, or number. The following Table summarizes the type character used forscanf()/scanf_s() family function.
Character | Type of input expected | Type of argument | Size argument in secure version? |
c | Character. When used with scanf() functions, specifies single-byte character; when used withwscanf() functions, specifies wide character. White-space characters that are ordinarily skipped are read when c is specified. To read next non–white-space single-byte character, use %1s; to read next non–white-space wide character, use %1ws. | Pointer to char when used with scanf() functions, pointer to wchar_t when used with wscanf() functions. | Required. Size does not include space for a null terminator. |
C | Opposite size character. When used withscanf() functions, specifies wide character; when used with wscanf functions, specifies single-byte character. White-space characters that are ordinarily skipped are read when C is specified. To read next non–white-space single-byte character, use %1s; to read next non–white-space wide character, use %1ws. | Pointer to wchar_t when used with scanf functions, pointer to char when used withwscanf() functions. | Required. Size argument does not include space for a null terminator. |
d | Decimal integer. | Pointer to int. | No. |
i | Decimal, hexadecimal, or octal integer. | Pointer to int. | No. |
o | Octal integer. | Pointer to int. | No. |
u | Unsigned decimal integer. | Pointer to unsigned int. | No. |
x | Hexadecimal integer. | Pointer to int. | No. |
e,E, f,g, G | Floating-point value consisting of optional sign (+ or –), series of one or more decimal digits containing decimal point, and optional exponent ("e" or "E") followed by an optionally signed integer value. | Pointer to float. | No. |
n | No input read from stream or buffer. | Pointer to int, into which is stored number of characters successfully read from stream or buffer up to that point in current call to scanf functions or wscanf() functions. | No. |
s | String, up to first white-space character (space, tab or newline). To read strings not delimited by space characters, use set of square brackets ([ ]), as discussed in scanf() Width Specification. | When used with scanf() functions, signifies single-byte character array; when used withwscanf() functions, signifies wide-character array. In either case, character array must be large enough for input field plus terminating null character, which is automatically appended. | Required. Size includes space for a null terminator. |
S | Opposite-size character string, up to first white-space character (space, tab or newline). To read strings not delimited by space characters, use set of square brackets ([ ]), as discussed in scanf() Width Specification. | When used with scanf() functions, signifies wide-character array; when used with wscanf functions, signifies single-byte–character array. In either case, character array must be large enough for input field plus terminating null character, which is automatically appended. | Required. Size includes space for a null terminator. |
Table 4. |
The a and A specifiers are not available withscanf(). The size arguments, if required, should be passed in the parameter list immediately following the argument they apply to. For example, the following code:
char string1[11], string2[9];
scanf("%10s %8s", string1, 11, string2, 9);
Reads a string with a maximum length of10 into string1, and a string with a maximum length of 8 into string2. The buffer sizes should be at least one more than the width specifications since space must be reserved for the null terminator.
The format string can handle single-byte or wide character input regardless of whether the single-byte character or wide-character version of the function is used. Thus, to read single-byte or wide characters with scanf() and wscanf() functions, use format specifiers as follows.
To read character as | Use this function | With these format specifiers |
single byte | scanf() functions | c, hc, or hC |
single byte | wscanf() functions | C, hc, or hC |
wide | wscanf() functions | c, lc, or lC |
wide | scanf() functions | C, lc, or lC |
Table 5. |
To scan strings with scanf() functions, and wscanf() functions, use the above table with format type-specifiers s and S instead of c and C.
The following Table describe the secure version of scanf_s() family.
Item | Description |
Function | scanf_s(),_scanf_s_l(),wscanf_s() and _wscanf_s_l() |
Use | Read formatted data from the standard input stream. These are versions of scanf(),_scanf_l(),wscanf(),_wscanf_l() with security enhancements. |
Prototype |
|
Parameters | format - Format control string. argument - Optional arguments. locale - The locale to use. |
Example | scanf_s( "%d %f %c %C %s %S", &i, &fp, &c, 1, &wc, 1, s, 60, ws, 60 ); |
Return value | Returns the number of fields successfully converted and assigned; the return value does not include fields that were read but not assigned. A return value of 0 indicates that no fields were assigned. The return value is EOF for an error or if the end-of-file character or the end-of-string character is encountered in the first attempt to read a character. If format is a NULL pointer. If execution is allowed to continue, scanf_s() and wscanf_s() return EOF and set errno to EINVAL. |
Include file | <stdio.h> or <wchar.h> for wscanf_s(),_wscanf_s_l() |
Remark | The scanf_s() function reads data from the standard input stream stdin and writes the data into the location given by argument. Each argument must be a pointer to a variable of a type that corresponds to a type specifier in format. If copying takes place between strings that overlap, the behavior is undefined. wscanf_s() is a wide-character version of scanf_s(); the format argument to wscanf_s() is a wide-character string. wscanf_s() and scanf_s() behave identically if the stream is opened in ANSI mode. scanf_s() doesn't currently support input from a UNICODE stream. The versions of these functions with the _l suffix are identical except that they use thelocale parameter passed in instead of the current thread locale. Unlike scanf() and wscanf(),scanf_s() and wscanf_s() require the buffer size to be specified for all input parameters of type c,C,s,S, or [. The buffer size is passed as an additional parameter immediately following the pointer to the buffer or variable. For example, if reading a string, the buffer size for that string is passed as follows:
char s[10]; scanf("%9s", s, 10);
The buffer size includes the terminating null. A width specification field may be used to ensure that the token read in will fit into the buffer. If no width specification field is used, and the token read is too big to fit in the buffer, nothing will be written to that buffer. In the case of characters, one may read a single character as follows:
char c; scanf("%c", &c, 1);
When reading multiple characters for non-null terminated strings, integers are used as the width specification and the buffer size.
char c[4]; scanf("%4c", &c, 4); // not null terminated
|
Table 6. |
Most of the security-enhanced CRT (C Run-Time) functions and many of the preexisting functions validate their parameters. This could include checking pointers for NULL, checking that integers fall into a valid range, or checking that enumeration values are valid. When an invalid parameter is found, the invalid parameter handler is executed.
The behavior of the C Runtime when an invalid parameter is found is to call the currently assigned invalid parameter handler. The default invalid parameter handler raises an Access Violation exception, which normally makes continued execution impossible. In Debug mode, an assertion is also raised. Also, if Watson crash reporting is enabled, which is the default, the application will crash and prompt the user if they want to load the crash dump to Microsoft for analysis.
This behavior can be changed by using the function_set_invalid_parameter_handler() to set the invalid parameter handler to your own function. If the function you specify does not terminate the application, control is returned to the function that received the invalid parameters, and these functions will normally cease execution, return an error code, and set errno to an error code. In many cases, the errno value and the return value are both EINVAL, indicating an invalid parameter. In some cases, a more specific error code is returned, such as EBADF for a bad file pointer passed in as a parameter.