This question already has answers here:
Is there any way to peek at the stdin buffer?
(3 answers)
Closed 8 years ago.
how can we see the contents of buffer assocaited with input file stream(STDIN) . suppose if we are giving input using scanf, getchar or any input function how it is actually getting stored in the buffer. especially when we press "enter" key .
example:
case:1)
$ input two integers:
10 20 (enter)
$ input two integers:
10(enter)
20(enter)
case 2:
$enter two characters
a b(enter)
$enter two characters
a(enter)
b(enter)
why in case 1 it is ignoring spacebar(ASCI-32) but in case2 it is taking spacebar as next input. is it propert of scanf function or terminal .
In the first case
Here it is ignoring the space bar because, according to the ascii character set " space " is
a character whose ascii value in decimal is 32.
When "%d" encounters the value 32 it ignores it because it cannot be an integer since
the integer literals have their range between 48(0) and 57(9).
whereas
in the second case we use "%c" to input characters for which the space(ascii - 32) is
a perfectly valid input, and thus is not ignored.
You can also use %d to input characters but then you will have to provide the ascii value
for a character that you want to input, for eg:
If you want to enter and display 'A' as character then your input must be 65.
Hope this helps to clear things a bit.
Related
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 4 years ago.
I mistakenly used scanf("%d\n",&val); in one of my programmes, I could not understand the behavior, the function showed.
int main(){
int val;
scanf("%d\n", &val);
printf("%d\n", val);
return 0;
}
Now the program required 2 integer inputs, and prints the first input that was entered.
What difference should that extra \n brings?
I tried to search but couldn't find the answer, even through manual of scanf.
An '\n' - or any whitespace character - in the format string consumes an entire (possibly empty) sequence of whitespace characters in the input. So the scanf only returns when it encounters the next non-whitespace character, or the end of the input stream (e.g. when the input is redirected from a file and its end is reached, or after you closed stdin with Ctrl-D).
From man scanf in my Linux box:
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
BTW, %d is also a directive.
So your "%d\n" has two directives, the first one reads the number and the second one... well reads any amount of white space, including your end-of-lines. You have to type any non-white space character to make it stop.
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 4 years ago.
I mistakenly used scanf("%d\n",&val); in one of my programmes, I could not understand the behavior, the function showed.
int main(){
int val;
scanf("%d\n", &val);
printf("%d\n", val);
return 0;
}
Now the program required 2 integer inputs, and prints the first input that was entered.
What difference should that extra \n brings?
I tried to search but couldn't find the answer, even through manual of scanf.
An '\n' - or any whitespace character - in the format string consumes an entire (possibly empty) sequence of whitespace characters in the input. So the scanf only returns when it encounters the next non-whitespace character, or the end of the input stream (e.g. when the input is redirected from a file and its end is reached, or after you closed stdin with Ctrl-D).
From man scanf in my Linux box:
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
BTW, %d is also a directive.
So your "%d\n" has two directives, the first one reads the number and the second one... well reads any amount of white space, including your end-of-lines. You have to type any non-white space character to make it stop.
I know the basics of scanf(); requiring a conversion specifier % and an address to the variable to store the input value &.
While doing an assignment, there was a task that involved inputting an arbitrary number of values, one example would be:
5 4 3 2 1
Into scanf, and then print out number of symbols corresponding to the integer typed (eg. '?'), so it would display the terminal as:
5 4 3 2 1
?????
????
???
??
?
In this case I had put the scanf in a while loop as so:
int i, num;
while(scanf("%d",&num)==1){
printf("%d",num);
for (i=0; i<num; i++){
printf("?");
}
printf("/n");
}
I am totally confused how scanf reads multiple integers in one input line (5 4 3 2 1) when many sources has specified that scanf only takes one integer until it reads a whitespace. From looking at this, my understanding is that the whitespace separating the integers indicate a new iteration following the previous integer?
When I tried to trace how printing works, it printed as:
5 4 3 2 1
5?????
4????
3???
2??
1?
...So my question is how does scanf 'save' all these integers in one line to 'num' and print EACH of the corresponding symbols to the values given AFTER input? Wouldn't integers be replacing the previous in the variable without an array?
Sorry if this question does not make sense - still quite new to coding. Thank you!
Your understanding of scanf is true, scanf only takes one integer until it reads a whitespace.
What makes you confused here is how the algorithm works. Your algorithm first reads the integer 5 and prints "immediately" five ?. It continues to read 4, print four ?, read 3, print three ?, and so on.
scanf stores the line in an internal buffer. If the buffer is not empty, it tries to read from the buffer and remove the portion that was successfully read; if the buffer is empty it waits for user input. On the first iteration of your outer loop (while), the buffer is empty. You input "5 4 3 2 1", so the buffer contains that. The first sscanf("%d",&num) reads the first integer from the buffer, which is 5; the buffer now contains " 4 3 2 1". On the second iteration you read 4, and the buffer will be " 3 2 1". This goes on until the buffer is exhausted. At this point your program continues; it just waits for more input.
scanf 'reads' characters from the standard input stream stdin (if there is nothing there yet it prompts the user to type something to be added to it), and converts them to a format depending on the conversion specifiers used in the format string.
You can think about stdin as a sequence of characters in the memory, and every time the user types something in the terminal and presses Enter what was typed is added to the stdin.
So in your case, when you type 5 4 3 2 1 and presses Enter in the terminal, stdin will receive the sequence of characters "5 4 3 2 1\n" (notice that the new line character was added when you pressed Enter).
Then the scanf("%d",&num), which is expecting only 1 decimal integer number, 'reads' and 'consumes' from stdin the relevant characters that form one continuous decimal integer number.
In this case 5 is read the first time scanf is executed, and " 4 3 2 1\n" is left in the stdin. Then as the condition is satisfied the loop statements are executed. And the second time scanf is executed the leading space is discarded by the %d specifier and 4 is read, leaving " 3 2 1\n" in the stdin. And so on until no decimal integers numbers can be read from the stdin...
Wouldn't integers be replacing the previous in the variable without an array?
There's no array required here at all.
The scanf() function takes the value (assuming white spaces included) and all of them are saved one by one into the variable num. If you use a debugger (suppose using GDB) and set a breakpoint in while(), you'll get to know by stepping into that the variable num is changed in each iteration and the for loop runs till num is reached.
An example of two iterations using a debugger is provided below (focus on num on the left corner):
Iteration 1:
Iteration 2:
I am very new to C programming. My sir gave this code to find the maximum of n numbers. When I do as Sir says things are perfect i.e Write a number when the line - Type the number of numbers and write numbers in a row like 7 8 9 10 when Type the numbers pop up.
#include <stdio.h>
main()
{
int n, max, number, i;
printf("Type the number of numbers");
scanf("%d", &n);
if(n>0)
{
printf("Type the numbers");
scanf("%d",&number);
max=number;
for(i=1; i<n; i++)
{
scanf("%d", &number);
if(number>max)
max=number;
}
printf("MAX=%d \n", max);
}
}
But if I write suppose - 5 8 9 10 7 6 - then the program understands it like --
It puts n = 5 then puts number = 8 then loop executes number changes to 9 then number changes to 10 till 6 and then gves max.
So how is scanf working here? It takes digit individually although they are written in a row with spaces?
From the horse's mouth:
7.21.6.2 The fscanf function
...7 A directive that is a conversion specification defines a set of matching input sequences, as
described below for each specifier. A conversion specification is executed in the
following steps:
8 Input white-space characters (as specified by the isspace function) are skipped, unless
the specification includes a [, c, or n specifier.284)
9 An input item is read from the stream, unless the specification includes an n specifier. An
input item is defined as the longest sequence of input characters which does not exceed
any specified field width and which is, or is a prefix of, a matching input sequence.285)
The first character, if any, after the input item remains unread. If the length of the input
item is zero, the execution of the directive fails; this condition is a matching failure unless
end-of-file, an encoding error, or a read error prevented input from the stream, in which
case it is an input failure.
10 Except in the case of a % specifier, the input item (or, in the case of a %n directive, the
count of input characters) is converted to a type appropriate to the conversion specifier. If
the input item is not a matching sequence, the execution of the directive fails: this
condition is a matching failure. Unless assignment suppression was indicated by a *, the
result of the conversion is placed in the object pointed to by the first argument following
the format argument that has not already received a conversion result. If this object
does not have an appropriate type, or if the result of the conversion cannot be represented
in the object, the behavior is undefined.
...
12 The conversion specifiers and their meanings are:
d Matches an optionally signed decimal integer, whose format is the same as
expected for the subject sequence of the strtol function with the value 10
for
the base argument. The corresponding argument shall be a pointer to
signed integer.
...
284) These white-space characters are not counted against a specified field width.
285) fscanf pushes back at most one input character onto the input stream. Therefore, some sequences
that are acceptable to strtod, strtol, etc., are unacceptable to fscanf.
The processing for scanf is exactly the same; the only difference is that scanf always reads from standard input.
Examples:
Suppose you type SpaceSpaceSpace123Enter in response to the first prompt; the input stream then contains the sequence {' ', ' ', ' ', '1', '2', '3', '\n'}. When you call scanf( "%d", &n );, scanf reads and discards the leading blank spaces, then reads and matches the sequence {'1', '2', '3'}, converts it to the integer value 123, and assigns the result to n. Since there was a successful conversion and assignment, scanf returns 1.
If the input stream contains the sequence {' ', ' ', ' ', '1', '2', '.', '3', '\n'}, scanf reads and discards the leading blanks, then reads and matches the sequence {'1', '2'}, converts it to the integer value 12, and assigns the result to n. The input stream will still contain {'.', '3', '\n'}. Since there was a successful conversion and assignment, scanf will return 1.
If the input stream contains the sequence {'.', '3', '\n'}, then there is no matching sequence of characters ('.' is not a valid character in a decimal integer). scanf will leave the . unread and leave the value of n unchanged. Since there was not a successful conversion and assignment, scanf returns 0 to indicate a matching failure.
If an end-of-file is signaled on the input stream before any matching characters have been read, or if there's some other input error, scanf does not assign any new value to n and returns EOF to indicate an input failure.
The "%d" in scanf("%d",&number); causes has 3 stages of scanning user text input into an int.
0 or more leading whites-space, like ' ', '\n', '\t' and some others are read and discarded.
Numeric text like "123", "-123", "+123" is read until until a non-numeric character is read. (or end-of-file, or a rare input error).
That non-numeric character is put back into stdin for subsequent input calls.
If step 2 is successful in reading at least 1 digit, the function returns 1. Good code checks the returned value.
if (scanf("%d",&number) != 1) Handle_UnexpectedInput();
The important thing is that '\n' is not so special with scanf("%d",&number);. It acts like a separator like another white-space or non-numeric text.
'\n' does cause the buffered stdin to accept the line of user input for processing by the various scanf() calls.
Here it is simplified explanation (not overly simplified, I hope) on how scanf works from a user point of view:
The arguments are divided in two parts:
The first part is a “format string”. The string is made of at least
one format specifier. In its simplest form a specifier begins with
% and it is followed by a letter that specifies the type of
variable you’re expecting (“%d” – I’m expecting an integer). The
number of specifiers must match the number of parameters and types
in the second part.
The second part is made of one or more addresses to locations memory
where the data you input will be stored. The pointed types must
match the specifiers.
When called, the function will repeat the following steps, starting with the first specifier and the first pointer, until the end of format string is detected:
Read and discard any white-space until a non-white-space character is found (white-space: space, tab, NL, at least);
Read characters up to first white-space or a character that do not match the expected input for current specifier;
Convert them to the type of current specifier and
Store the result in the location pointed by the current pointer.
There are three typical beginner mistakes which will result in undefined behavior (crash, most likely):
You forget the address-of operator &.
The specifier and the type do not match.
The number of specifiers do not match the number of pointers.
int d;
scanf( "%d", d ); // no &
scanf_s( "%s", &d ); // s do not match int
scanf_s( "%d%d", &d ); // too many specifiers
when you press the keyboard, you are filling a buffer on your computer. the scanf will read the amount of consecutive data untill it hit a space, so "1234 43", on the code scanf("%d") you are saying "read one number", and 1234 is one number, that's what it will read.
But if you have a loop that will execute that scanf again, the number "43" is currently in the reading buffer, and scanf will read it without stopping.
The manual for scanf doesn't explains that and it's a bit confusing for a newcomer to understand why the application is not stopping there to read a new number.
Let me explain as simply as possible...
scanf reads bytes from the standard input stream stdin.
Let's say the input you give is "23 67 21 99\n" (The \n is from when you pressed Enter).
Then each next call to scanf will start reading from this input buffer and it will interpret what is sees as whatever you tell it ("%d", etc) while separating inputs by an empty character. This could be a new line, a space, a tab, etc.
While there are still bytes to be read, scanf will not wait for you to input. That is what is happening here.
let's keep it simple. I assume you don't know anything about buffer or stdin.
scanf is used to take input from user. Whenever you type a number and press 'space' or ' enter' on keyboard the number is entered into program for further purposes. When you type scanf("%d",&n); it mean take integer input from the user and store it on the address of variable n.
I wanted to write a function to in C to read characters until a newline is encountered. I wrote the following codes using scanf and getchar:
Code using scanf :
while(scanf("%c",&x)!=EOF&&x!='\n'){....}
Code using getchar : while(((x=getchar())!=EOF)&&x!='\n'){....}
int x is a local variable declared inside the function. The second code stops after reading word (EG: "ADAM\n"), while scanf code does not break the loop and keeps on waiting.
Later I found that after scanf, x's value was (2^7-1)*(2^8) + ascii value of character read ( = 32522 for newline), while character constant '\n' was 10. So the comparison was failing.
My question is that why scanf assigns a value > 32000 to x after reading '\n', while getchar assigns a value 10( which matches with character constant '\n') ?
The key difference here is in the scanf behavior:
1) in general scanf is used to read different data types (not only char), for example scanf("%d",&num) will read integer number and ignore all "space" characters (characters as ' ' (space), '\t' (tab) and '\n' (new line)).
2) scanf("%c",&x) as well as scanf("%d",&num) (if number was entered) will return 1 - number of successfully data read from stdin. Note: scanf("%d",&num) will return 0 if not number is in stdin.
The main difference is that scanf does skip whitespace characters in the input stream, while getchar returns them. So you can't see newlines in the input with scanf. Also the return value of scanf is the number of successful converted variables.
You need to check for scanf(...) == 1 to see, if the variable contains a valid value (more details here). When scanf did not converted all the input variables, the value of the not converted variables is undefined. This is why you see the strange value for x in your case. This is just some (more or less) random value caused by the fact that the compiler assigned x to a memory location, which was used before, and still contains some left over data.