Where is scanf() reading input from, if not from the keyboard? - c

I'm a novice programmer getting introduced to C and I'm missing something fundamental about the way my scanf() works. I want to read a single int from the keyboard with code like this:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int userBookSelection;
scanf("%i", &userBookSelection);
printf("Printing userBookSelection: %i", userBookSelection);
return EXIT_SUCCESS;
}
When I run the code, the console stays black until I stop debugging. There is never a cursor waiting for keyboard input. When I stop debug I can see this output in the console, same every time:
Printing userBookSelection: 2130567168
I'm debugging in Eclipse with MinGW GCC compiler on Windows. The code syntax seems to be correct -- is it possible there's something wrong in my build path to make this happen? I need to know why scanf() isn't reading for keyboard input.

So I've gotten a line of code from my professor which takes care of this bug -- whether it's a necessary solution particular to Eclipse and/or MinGW I'm not sure. In any case, here's the code with the additional line:
int main(void) {
int userBookSelection;
setvbuf (stdout, NULL, _IONBF, 0);//<---The magic line
scanf("%i", &userBookSelection);
printf("Printing userBookSelection: %i", userBookSelection);
return EXIT_SUCCESS;
}
I'd appreciate any additional wisdom on what's going on, what setvbuf() is doing and how scanf() works more fundamentally.

Related

How does the infinite loop further down stop earlier code from execution?

I've come across this weird situation i can't wrap my head around. In the following code, the Program is apparantly enetering the infinite loop, but doesn't execute the code that comes before it.
#include <stdio.h>
#include <stdlib.h>
int main() {
char buf[100];
if (scanf("%s", buf)==EOF) return 0;
printf("This does not get printed");
while(1) {} //infinite loop
return 1;
}
Somehow, the printf command does not get executed, even after pressing enter or using Ctrl-d.
However, it seems as if the code would end up in the infinite loop.
Does anyone explain whats going on here? I'm using gcc.
Standard output is line buffered by default. If you write less than a line to the output, some or all of it can be delayed until more output occurs.

C Scanf Command Won't Run

I am a new learner to the C language. I am trying to figure out how to use scanf. This is my code so far.
#include <stdio.h>
#include <string.h>
int main() {
char lastInitial;
printf("What is your last inital?");
scanf(" %c", &lastInitial);
}
When I run this code (I'm using VS Code), it shows that the file is running, but nothing shows up. When I go to the top to click the run button again, it says this code is already running. If I stop the run, delete the scanf line and run again, the file runs and displays "What is your last inital?" I am confused as to why adding scanf to the file stops the printf and doesn't allow any user input.
You might have run into a little intricacy with how printf works. When you run printf("What is your last inital?");, this text does not end with a newline (\n) character. As a result, some environments might not display it right away, delaying it until you printf a complete line or until the program ends. This is done for efficiency, since the internal steps to actually get output to your screen are a bit expensive.
When you remove the scanf, the program ends right after the printf; as the program is ending any text that's still waiting to be displayed gets sent to the screen by the built-in shutdown routines in the C standard library. However, when the scanf is included, the text gets buffered/delayed, and doesn't ever get sent to the screen sine the program is stalled waiting for user input. You can force the output to be sent immediately using a newline:
#include <stdio.h>
#include <string.h>
int main() {
char lastInitial;
printf("What is your last inital?\n");
scanf(" %c", &lastInitial);
}
Or if you don't want a newline, you can tell the C standard library to explicitly send all output text right away:
#include <stdio.h>
#include <string.h>
int main() {
char lastInitial;
printf("What is your last inital?");
fflush(stdout);
scanf(" %c", &lastInitial);
}
When you run the program, you should switch from "OUTPUT" to "TERMINAL".
You need to install the "Code Runner" extension.
Then go to File-->Preferences-->Settings in the search write code runner, and below will appear some settings of code runner, you need to find Run In Terminal, and turn it on.
THAT'S ALL :)

fgets loop ending with EOF skips next fgets

I'm trying to get a user input after an undefined amount of another input done. But the problem is that the second fgets after the while loop never gets invoked. I'm ending the loop with EOF, maybe that's the error. But I don't know how else I should end the loop.
Another funny thing is: It's a task from my C coding class and the lecturer has a video of her solution, and if I'm copying her code 1:1, it also does not work. It also skips the second fgets call.
I've already cut down the code to an absolute bare minimum to get the error, but as you can see: a few lines of code and it does not work. I even tried debugging it with GDB, but I can't figure out how to have it behave like it does in the video.
#include <stdio.h>
int main() {
char input[80];
while (fgets(input, 80, stdin) != NULL) {
// nop
}
fgets(input, 80, stdin);
printf("%s\n", input);
return 0;
}
when you press ctrl+d = EOF in mac (on windows its the same i guess) for the first time you had to exit the while loop.
when you press it again the fgets after the loop works and it prints the last line.
sorry for my english :)
for LINUX and UNIX systems it's ctrl +D and ctrl + z for windows. you can test it out using the following code.
#include <stdio.h>
int main() {
char input[80], input1[50];
while (fgets(input, 80, stdin) != NULL) {
// nop
}
fgets(input1, 50, stdin);
printf("input is %s\n", input);
printf("input1 is %s\n", input1);
return 0;
}
Also, mention your system in the post for further clarification
Update: I got the problem! Found out that on every OS that the code worked, libc was in version 2.27. On all other systems libc was in version 2.29. So I compiled the code with the -static option on a libc-2.27 System and copied it to my main system with libc-2.29 and everything worked as inspected!
So now I just have to figure out, how to downgrade my libc to 2.27 on Manjaro.
Edit: Got a mail from the developers. They say the way it behaves on my system is the correct way and linked to commit 2cc7bad0ae. So apparently my lecturer used a bug for her solution.

pre-fill stdin in C

My program is supposed to let the user edit a line of a file. The user edits the line and sends it back by pressing enter. Therefore I would like to print the current line which is about to be edited, but kind of print it on stdin instead of stdout.
The only problem I don't know how to solve is how I can prefill the stdin. I've already tried this:
char cprefill[] = {"You may edit this line"};
char cbuffer[100];
fprintf(stdin, cprefill);
fgets(cbuffer, 100, stdin);
This seems to be the simplest solution, but is probably too simple to work. The fprintf doesn't print anything to stdin. What is the correct way?
Edit:
This is how it is supposed to look like. Please mind the cursor which can be moved.
The C language has no notion of terminal nor of line edition, so it cannot be done in a portable way. You can either rely on a library like [n]curses to get an almost portable solution, or if you only need that on one single OS use low level OS primitives.
For exemple on Windows, you could feed the input buffer by simulating key strokes into the appropriate window (for example by sending WM_CHAR messages) just before reading, but that would be highly non portable - and in the end is no longer a C but a Windows solution...
First you need the libreadline developer package. (You might also need the libreadline if it's not already available on your system)
On Debian / Ubuntu that's apt install libreadline-dev (plus libreadline6 if you need the binaries also - 6 might be different on your platform)
Then you can add an history to readline, like this
#include <stdio.h>
#include <readline/readline.h>
#include <readline/history.h>
...
char cprefill[] = {"You may edit this line"};
add_history(cprefill);
char *buf = readline("Line: ");
printf("Edited line is %s\n", buf);
// free the line allocated by readline
free(buf);
User is prompted "Line: ", and has to do UP ARROW to get and edit the history, i.e. the cprefill line.
Note that you have to compile/link with -lreadline
readline prints the prompt given as argument, then waits for user interaction, allowing line edition, and arrows to load lines stored in the history.
The char * returned by readline has then to be freed (since that function allocates a buffer with malloc()).
You could use GNU Readline. It calls the function that rl_startup_hook points to when starting, where we use rl_insert_text to put our text in the line buffer.
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
int prefill(void)
{
rl_insert_text("You may edit this line");
return 0;
}
int main(void)
{
char *cbuffer;
puts("Please edit the following line");
rl_startup_hook = prefill;
if ((cbuffer = readline(NULL)) == NULL) /* if the user sends EOF, readline will return NULL */
return 1;
printf("You entered: %s\n", cbuffer);
free(cbuffer);
return 0;
}
For more information, see the GNU Readline manual.

Printf not working with scanf

Hi i am new to the programing and for example in my code:
#include <stdio.h>
int main (void){
int a;
printf("Write a number: ");
scanf("%d", &a);
printf("Your written number was: %d", a);
return 0;
}
Printf does not write "write a number" in console when i start the program but only after i already inserted the number and pressed enter.
I have already done some research and found out for this code:
setvbuf(stdout, NULL, _IONBF, 0);
when i paste this into my program it works as it should but i am wondering why do i have to do that?
when i paste this into my program it works as it should but i am
wondering why do i have to do that?
It's because printf() is usually line-buffered when attached to a terminal. So disabling the buffering with the call to setvbuf() makes stdio library to not buffer at all.
You can also use fflush(stdout); after the printf() call to flush out the buffered output. The same can be done with setbuf(stdout, NULL); as well.
You can also add a \n at the end of printf() statement to force the flushing. But this will work only if the output goes to a terminal device.
For example, if you do (on a unix-like system):
./a.out > output_file
then the \n will not flush the buffer.
Out of the two options (setbuf() and fflush()),fflush(stdout); is probably the better option in most cases. Since disabling the buffering completely can have negative impact on performance (which is the primary reason for buffering in the first place) whereas fflush() can be judiciously used at the right place when you think it's necessary.
printf has a buffer. It is a mechanism to make code run faster by not having to switch between the user context and the kernel context. To get over this you can tell the code to flush the buffer - i.e. send it to the operating system. This can be done by
fflush(stdout);
After a printf. If the printf contains a new line this is done automatically.
You probably want \n in each of those printf statements.
Add linefeed "\n" to your printf lines like so:
printf("Write a number: \n");

Resources