fwrite doesnt print anything to stdout - c

When I run this small code and enter 3 integers on the console, it doesn't print out as it should due to the fwrite statement. It prints only after I keep hitting enter for some time. Help?
P.S: Learning faster ways than scanf and printf.
#include<stdio.h>
int main(){
int size[3];
fread(&size,sizeof(int),3,stdin);
fwrite(&size,sizeof(int),3,stdout);
fflush(stdout);
return 0;
}

This is because fread reads binary data, not formatted text, so when you tell it to read 3 "ints" it will read 3*4=12 bytes of raw data from stdin. If you type "1" "2" "3" that's only three bytes of text, plus three newlines. Once you type twelve bytes it will probably get past that part, but then your program is probably broken, assuming you wanted to read and write actual text.
You mean you're "learning faster ways than scanf and printf." Well, this is not a faster way, it's just a broken way. If you're having a performance issue in some code using scanf & printf, please ask a separate question and we can help with that.

Size of int is 4 bytes so your fread() will try to read 12 bytes (4 * 3).
When you enter something like this on console
1 2 3
it is 6 chars = 3 numbers + 2 spaces + 1 \n
Hence you would have to press enter at lease 6 times so that it reads 6 more bytes.
Better to use scanf() to get integers as
scanf("%d %d %d", &size[0], &size[1], &size[2]);

Related

Why does having scanf & printf in a loop cause this output

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.

Printing text too often?

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.

C - How scanf inputs work and how it iterates in loops?

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:

fgets() getting skipped, how to clear user input?

I am using fgets() to get user input, and then I parse it into a double using sscanf(). Here is my example code:
int menuItem = 0;
char input[3];
printf("Enter valid menu item"); //values are 1, 2, 3, 4, 5, and -1
fgets(input, sizeof input, stdin);
sscanf(input, "%d", &menuItem);
The error occurs if the user enters 3 digits (invalid input, and I want to handle it accordingly), it skips my next fgets() by automatically placing the third digit as the next input. For example, if the user inters 123, it will now skip the next fgets and use the value 3 as the input. How can I clear this, or at most, only read 1 digit (but still being able to handle -1).
Why don't you just make your input array larger? Like 50 bytes... If the user enters that many, they are idiots and deserve strange behaviour =)
This is of course inelegant, but putting it in perspective, you are probably not writing industrial-strength code here. You just want to fix a silly bug, and this is the simplest solution.
[edit]
In case you are confused as to why I suggested this. Your input array is only large enough to hold 2 values, plus a null-terminator. So obviously, you want it to be large enough that you can be sure the user entered a single choice and not two choices
Your input buffer allows 1 digit, 1 newline, and 1 terminal null '\0', which really isn't big enough.
Suppose the user types 100 followed by a newline. The first call to fgets() will read 2 digits (10), then the second call will read the third digit and newline; then the next call will wait for the next input.
Simply increase your buffer size to something more sensible. For a lot of programs that I write, I use a buffer size of 4096. The POSIX standard sets _POSIX2_LINE_MAX to 2048. If you're unhappy with that, simply go with a convenient number like 64 or 128; you won't go too far wrong.
Your technique with fgets() and sscanf() is definitely the better direction to go, but you should check that sscanf() parsed the correct number of values. One of the advantages of fgets() plus sscanf() is that you can make better reports about what was erroneous in the line that the user entered; this is much less easy to do if you use fscanf() or scanf() directly.

i am very confused about reading from txt file

sorry i'm new at c
i want to read these data from txt file.
A 7
c 5
y 6
U 9
j 4
Z 3
z 5
0
here is my code
while(feof(input)==0){
char c;
int num;
fscanf(input,"%c%d",&c,&num);
printf("%c:%d\n",c,num);
}
but result in console is not same as txt file
the result is
Open file complete
A:7
:7
c:5
:5
y:6
:6
U:9
:9
j:4
:4
Z:3
:3
z:5
:0
my code is correct, isn't it?
fscanf(input,"%c%d",&c,&num);
my code is correct, isn't it
You're not eating the newlines. Change that to:
fscanf(input,"%c%d ",&c,&num);
^
As explanation, each line ends with a a character, '\n'. If you don't do anything about it, %c will try to read it and you'll get confusing results. A cheap trick is to add a blank space in fscanf which makes it eat all blanks after a %c%d couple.
EDIT
In light of comment from Peter Kowalski:
shouldn't it be fscanf(input,"%c %d ",&c,&num); ? I've put additional
space between %c and %d
This is a very good question. Thing is %d is one of the specifiers that ignore leading space. No matter how many blanks are in the stream, scanf will eat and discard them. Therefore a blank before %d is implicit.
You also need to eat the newlines.
fscanf(input,"%c%d\n",&c,&num);
Quick fix: simply adjust your printf() statement from
printf("%c:%d\n",c,num);
to
printf("%c %d",c,num);
There are other ways, like adjusting your current scanf(), which is better as it fixes the problem at the source (you are reading and keeping the newline).
Alternatively you could just read the whole line without parsing it into components and print it out.

Resources