The program in question:
#1:
int main(void) {
int size;
scanf("%d", &size);
int v[size];
for(int i = 0; i < size; ++i) {
scanf("%d", &v[i]);
printf("the %d-th element is : %d\n",i, v[i]);
}
return 0;
}
O/P:
5
6 7 8 9 10 11
the 0-th element is : 6
the 1-th element is : 7
the 2-th element is : 8
the 3-th element is : 9
the 4-th element is : 10
My question: Why does it seem like the program does all the print statements after your input?
So does the program kind of 'hold' the print statements to display them after you press <Enter> for a new-line? Is there a better explanation of this behavior somewhere?
**Edit after #dbush's answer**
I need a bit of a clarity on this: so let's say the `size = 5` & my input is `6 7 8 9 10` so I'm asuming the first `scanf` in the loop reads the `6 ` part then reads/stores the data and then passes the rest of the content that's in the input buffer to the next `scanf`'s leaves the rest of the input data in the `input buffer`
Then the program goes towards the printf statement stores that output in some sort of a buffer then it loops back to the 2-nd scanf and that reads the 7 part and all of this goes till the 10<enter> part, now the final scanf reads/stores 11 and since there's a newline, the programs decides that it no longer needs to read from the input buffer and now outputs the rest of the contents from the output buffer to the console.
Is this how it goes or are there some inaccuraries in this analogy?
Edit #2: I found this good blogpost explaining what goes on with scanf's & the input buffer, together with #dbush & #Weather Vane answers to completely answer any doubts I've had regarding this
When reading from a terminal, nothing gets sent to scanf until you press ENTER.
So in your case, you have 6 strings which look like numbers in the input buffer. The first scanf reads just the first number, because that's what its pattern is looking for and leaves the rest in the input buffer. Then the program continues by calling printf, and because the string ends with a newline it gets printed immediately. When the program then loops back around to scanf, there's already data in the input buffer so it reads what's there and returns immediately, and the cycle continues.
So only the first call to scanf is waiting for input from the user, while the others are reading what's already in the input buffer, and the printf calls are having their output go to the terminal immediately since the string to print ends with a newline.
Related
i am new to c and have used python before. This whole buffer overflow stuff is really breaking my mind.
#include <stdio.h>
int main(){
char str1[3];
while(true){
scanf("%2s", str1);
printf("test\n");
}
}
This is a little code i've written to test the syntax and the stdio library. I was really suprised when the program outputted "test" multiple times, depending on how many characters i entered. So for example, when I entered two characters, it printed "test" two times. Can anyone please tell me why this is happening and how I can fix it?
You can figure out what happens by modifying your code as follows:
#include <stdio.h>
int main(){
char str1[3];
while( 1 ){
scanf("%2s", str1);
printf("test: %s\n", str1);
}
}
which simply prints the contents of the str1 alongside of the "test" string.
Here is an example output for an input string of 1234567:
1234567
test: 12
test: 34
test: 56
test: 7
The scanf("%2s", str1); statement reads two characters from the stdin and assings them to the str1. The read characters are "popped" from the input stream, i.e., they are removed. If the stdin happens to contain more characters, the excess ones are left untouched. Therefore, for the given input, when the first scanf is returned, the str1 containes 12\0, and the stdin contains 34567.
Since these are in the infinite loop, the code repeats, scanf gets called again, reading the first two characters from the stdin again, only this time finds 34.
And the process repeats, untill there are no characters left on the stdin, then the scanf waits for the user input, presumably as you would have expected.
Basically, scanf keeps reading instead of waiting for user input, since the stdin already contains something to read.
So for example, when I entered two characters, it printed "test" two times.
This on the other hand, does not make sense, as it should be printing "test" for N/2 times, rounded up, where N is the number of characters you enter.
There is not much that I can suggest for "fixing this", since it is not really clear what you are expecting. But if you want to get rid of the remaining characters in the stdin, you can check this.
You need to clear your input buffer as per this answer
Otherwise, you'll read from the stdin, print it, jump back to the loop head and continue reading, if there is still something in the buffer.
Each time through the loop, scanf("%2s", str1) reads at most 2 non-whitespace characters from the input stream. If there are more than 2 non-whitespace characters available in the stream, the loop will continuously call scanf (and printf) until scanf blocks waiting for data. If the input stream contains ffff\n and has not yet been closed (eg, a user is entering data interactively from a tty), the first 2 calls to scanf will immediately return and printf will be called twice. The 3rd call to scanf will block until more data is available, or the stream is closed, or there is an error.
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:
This question already has answers here:
What is the effect of trailing white space in a scanf() format string?
(4 answers)
Closed 3 years ago.
in my code according to for loop Condtion it is clear that it must iterate only 5 times from 0 to 4.
But it is taking 6 input from the user.
Why it is happening.
Please clear my doubt.
#include <stdio.h>
#include <conio.h>
void main() {
int i, num;
clrscr();
printf("Enter 5 elements in the array\n");
for (i = 0; i < 5; i++) {
scanf("%d\n", &num);
}
getch();
}
According to your code i think you are mixing up the inputs you request with the system pause created by the getch() function you call at the end. The getch() initiates a pause which you can easily mix up with your input prompts since during this pause, user input is possible though not considered.
I propose you introduce an instruction in the loop which indicates the line or some information so you can make the distinction.
You have two problems regarding input.
The first is the getch call at the end of the program. But the other problem is the newline in the scanf format string
scanf("%d\n",&num);
When the scanf function sees a space in the format string (newline is considered a space in this context) then it will read and discard all spaces in the input. The problem with a trailing space in a format string is that to know when the spaces in the input ends, there must be some non space input as well.
So (almost) never have a trailing space (space, newline, carriage-return, tab) in a scanf format string.
The reason this code wait 5 times user input is the getch() at the end.
It waits for the input of one character and probably used to prevent the shell window from directly closing after the program finshed.
IF "for loop" is like this,
for(i=0;i<5;i++)
{
scanf("%d",&a[i]);
}
Then,
Input can be given either as,
1
2
3
4
5
Hitting Enter Every time for the next Input.
OR
1 2 3 4 5
With space character between different input values.
Now, How does this thing work?
I mean if loop is running,
then how does it recognizes that Input is given for the next loop cycle wihtout hitting the Enter key.
How does this thing work?
This works because scanf() reads only till a space or newline or tab is encountered.
So, when you give input 1 2 3 4 5, at the first iteration scanf() reads 1 and a space is encountered and scanf() terminates keeping the value 1 to a[0]. At the next iteration2` is read the same way.
The scanf (and family) function with the "%d" format reads white-space delimited input. If the white-space is a newline or a single space doesn't matter.
The Enter key simply tells the input stream system that input is ready (stdin which is used by scanf is line buffered by default), exactly what that input is doesn't matter.
This question already has answers here:
'printf' followed by 'scanf' requires pressing ENTER key twice to accept input
(2 answers)
Why does scanf ask twice for input when there's a newline at the end of the format string?
(7 answers)
Closed 5 years ago.
I'm beginner in C. Please dont mind if my question is lame. In this program which i have written, when I use 'for' loop first time , I expect only 3 values is stored in an array but it stores 4 values and in next 'for' loop as expected show 3 values.
My Question is why in 1st 'for' loop it takes 4 values instead of 3?
#include<stdio.h>
void main()
{
int marks[3];
int i;
for(i=0;i<3;i++)
{
printf("Enter a no\n");
scanf("%d\n",(marks+i));
}
for(i=0;i<3;i++)
{
printf("%d\n",*(marks+i));
}
}
\n in scanf was the problem
#include<stdio.h>
int main()
{
int marks[3];
int i;
for(i=0;i<3;i++)
{
printf("Enter a no\n");
scanf("%d",(marks+i));
}
printf("\nEntered values:\n");
for(i=0;i<3;i++)
{
printf("%d\n",*(marks+i));
}
return 0;
}
Reason:
I expect only 3 values is stored in an array but it stores 4 values
and in next 'for' loop as expected show 3 values. My Question is why
in 1st 'for' loop it takes 4 values instead of 3?
First: No, it only stores 3 number but not 4 numbers in array marks[].
Second: interesting to understand loop runs only for three times for i = 0 to i < 3. The for loop runs according to condition. More interesting code is stuck in scanf() as described below:
Your confusion is why you have to enter four numbers, its not because you loop runs 4 times but its because scanf() function returns only when you enter a non-space char (and after some enter press you inputs a number symbol that is non-space char).
To understand this behavior read manual: int scanf(const char *format, ...);:
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.
Because in first for loop's, in scanf() you have included \n in format string, so scanf() returns only if press a number enter (or a non-space key).
scanf("%d\n",(marks+i));
^
|
new line char
What happens?
Suppose input to program is:
23 <--- because of %d 23 stored in marks[0] as i = 0
<enter> <--- scanf consumes \n, still in first loop
543 <--- scanf returns, and leave 542 unread,
then in next iteration 543 read by scanf in next iteration
<enter>
193
<enter> <--- scanf consumes \n, still in 3rd loop
<enter> <--- scanf consumes \n, still in 3rd loop
123 <--- remain unread in input stream
remove \n
and i can be created in the if statement as for (int i = 0; i < 3; i++) {}