The strangeness of white space characters in the standard input stream-distinguishes scanf From CIN

Source: Internet
Author: User

2011-04-15 wcdj

 

On the forum, we can see that someone raised the following question. Here we will summarize it.
Original problem:
Http://topic.csdn.net/u/20110414/22/90d0606c-9876-48e4-9b69-bd8bd8a41897.html

 

# Include <stdio. h> <br/> int main () <br/>{< br/> int ival1 = 123, ival2 = 1; <br/> char CH = 'T '; <br/> scanf ("% d", & ival1, & ival2); <br/> scanf ("% C", & Ch ); <br/> printf ("% d/n % C/N", ival1, ival2, CH); <br/> return 0; <br/>}< br/>/* <br/> enter 2 and press Enter. <br/> the result is: <br/> 2 <br/> 1 <br/> A <br/> */<br/>

 

 

LZ's question is:
: But the first carriage return is still in the buffer zone! Why is it not read by the variable ch?
I will describe the above problem in detail: that is, after entering the variable ival1, there is a linefeed '/N' in the input buffer ', then, enter a character "A" on the keyboard. the LZ question is, why didn't the variable ch read the line break '/N, instead, it skips and reads the character a entered later.

Explanation

In many lexical/syntax analyzer, whitespace refers to any number of basic blank characters (including spaces, tabs/t, carriage returns/R, line breaks/N, etc) continuous combination. Note: In C/C ++ programming languages, a C-style string is also called a null-terminated string. It is generally translated as a string ending with a null character. It is null here (note, it is a character '/0', or the character encoding value is 0. The standard library of C has a function. The isspace (char c) function can detect whether a character is a blank character and must contain the header file of cctype.

View two situations of scanf
:

Case 1: After ival1 is input, no matter how many whitespaces are entered, the system will continue to wait for ival2. The reason is that the whitespace is regarded as the input separator and will be ignored.

Int ival1, ival2; <br/> scanf ("% d", & ival1); <br/> scanf ("% d", & ival2 );

Case 2: After the ival is input, the variable ch also reads data from the stdin stream, and the output shows that the ASCII code value of CH is 10, that is, the linefeed '/N '. The linefeed is a whitespace and should be used as a separator, but it is used as a valid character to be read into the variable ch.

Int ival; <br/> char ch; <br/> scanf ("% d", & ival); <br/> scanf ("% C", & Ch );

Then compare the two cases of CIN
:(Note case 2
)

Case 1: After ival1 is input, no matter how many whitespaces are entered, the system will continue to wait for ival2. The reason is that the whitespace is regarded as the input separator and will be ignored.

Int ival1 = 0, ival2 = 0; <br/> CIN> ival1; <br/> CIN> ival2;

Case 2: After the ival is input, no matter how many whitespaces are entered, the white space remains waiting for the input ch. Note: This is different from scanf!

Int ival = 0; <br/> char ch; <br/> CIN> ival; <br/> CIN> CH;

Conclusion

:
(1) When the format specifiers in scanf is not "% C", whitespace serves as a separator. Assign values to the two data pairs that are separated to the defined variables or arrays respectively. The whitespace between the two data is read from the buffer but does not work, of course, the last '/N' will be left in the buffer unless it is read by getchar (); or scanf ("% C", & Ch.
(2) When the format specifiers in scanf is "% C", whitespace will be read normally and will no longer serve as a separator.
(3) When using Cin, white spaces are ignored as separators.

Note:
:
(1) When you press the Enter key on the keyboard, two characters are generated: The carriage return ('/R') and the line feed ('/N '). Carriage Return '/R' (Cr: Carriage Return: Reversing) enables the cursor to return to the first line of the line, line feed ('/N') (new line) and then line feed.
(2) The carriage return is required, whether it is getchar (); or scanf, as long as the function inputs data through the buffer zone is waiting for the carriage return '/R' to appear before entering the buffer zone.

Format specifiers:
A sequence formed by an initial percentage sign (%) indicates a format specifier, which is used to specify the type and format of the data to be retrieved from stdin and stored in the locations pointed by the additional arguments. A format specifier follows this prototype:
% [*] [Width] [modifiers] Type

 

Let's look at the LZ issue.

The problem with LZ is why the variable ch does not read the line break '/N', but skips it and reads the character a that is entered later.
The reason is: after ival1 is successfully read, the next data format to be read is "% d". Therefore, the linefeed '/N' is ignored, therefore, the next non-blank character 'a' is read, that is, the value of the variable ch is 'A '.
Note that variable B does not read valid data. Therefore, variable B is still the original initial value. The return value of scanf can be used to determine the number of successfully read data (input from the keyboard.

Scanf

# Include <cstdio> <br/> # include <cstdlib> <br/> # include <cctype> <br/> int main () <br/>{< br/> int ival1 = 0, ival2 = 0; <br/> char CH = 'T'; <br/> char ch_tmp; <br/> scanf ("% d", & ival1); <br/> scanf ("% C", & ch_tmp ); <br/> If (isspace (ch_tmp) <br/>{< br/> printf ("% d is a whitespace right? % D is the newline character! /N ", ch_tmp, ch_tmp); <br/>}< br/> If (scanf (" % d ", & ival2 )! = 1) <br/>{< br/> printf ("damn it! Ival2 cannot read input! /N "); <br/>}< br/> scanf (" % C ", & Ch ); <br/> printf ("% d % C/N", ival1, ival2, CH); <br/> system ("pause "); <br/> return 0; <br/>}< br/>

 

CIN

# Include <iostream> <br/> # include <cctype> <br/> using namespace STD; <br/> int main () <br/>{< br/> int ival1 = 0, ival2 = 0; <br/> char CH = 'T'; <br/> char ch_tmp; <br/> CIN> ival1; // read and ignore all white spaces before valid characters, and then read the characters until the white spaces are encountered again. The read ends, this blank character remains in the input stream <br/> CIN> ch_tmp; // note: the difference between this character and scanf is ignored, instead of being a valid character <br/> If (isspace (ch_tmp) <br/>{< br/> cout <ch_tmp <"is a whitespace right? "<Ch_tmp <" is the newline character! "<Endl; <br/>}< br/> CIN> ival2; <br/> If (! CIN) <br/>{< br/> cout <"damn it! Ival2 cannot read input! "<Endl; <br/>}< br/> CIN> CH; <br/> cout <ival1 <"" <ival2 <"" <ch; <br/> system ("pause "); <br/> return 0; <br/>}< br/>

 

Verify the version of CIN:

# Include <iostream> <br/> # include <cctype> <br/> using namespace STD; <br/> int main () <br/>{< br/> int ival1 = 0, ival2 = 0; <br/> char CH = 'T'; <br/> char ch_tmp; <br/> streambuf * Sb; <br/> Sb = cin. rdbuf (); <br/> cout <Sb-> in_avail () <Endl; // will print 0 <br/> CIN> ival1; // read and ignore all the white spaces before the valid characters, and then read the characters until the white spaces are encountered again. The read ends, this blank character remains in the input stream <br/> cout <Sb-> in_avail () <Endl; // will print 1 to prove that the white space character '/N' is indeed left in the input stream <Br/> CIN> ch_tmp; // note: the difference between this parameter and scanf is ignored, instead of being a valid character <br/> If (isspace (ch_tmp) <br/>{< br/> cout <ch_tmp <"is a whitespace right? "<Ch_tmp <" is the newline character! "<Endl; <br/>}< br/> CIN> ival2; <br/> If (! CIN) <br/>{< br/> cout <"damn it! Ival2 cannot read input! "<Endl; <br/>}< br/> CIN> CH; <br/> cout <ival1 <"" <ival2 <"" <ch; <br/> system ("pause "); <br/> return 0; <br/>}< br/>

 

Reference
:
Scanf
Http://www.cplusplus.com/reference/clibrary/cstdio/scanf/

Getchar, scanf, and buffer
Http://blog.csdn.net/weinixugeyuan/archive/2009/03/12/3980498.aspx

Difference between getch (), getche (), and getchar ()
Http://www.cnitblog.com/mantou/archive/2010/01/13/1250.html

IOS: rdbuf
Http://www.cplusplus.com/reference/iostream/ios/rdbuf/

Http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/57d90614-8555-488c-acc4-f53fb04baaa3

 

 

 

 

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.