can scanf be terminated on pressing some specific key other than enter - c

I have a situation here
i am taking input from user
using scanf can I terminate the scanf as soon as user presses the # key
please enlighten me on this

No, scanf() (or rather stdin, by default) is line-oriented so it needs to read a full line.
Look into ncurses or similar libraries for "raw" key-by-key input.

Related

How getchar() works when it is used as condition in while loop

I cant understand how the following code really works.
int main() {
char ch;
while((ch=getchar())!='\n')
{
printf("test\n");
}
return 0;
}
Lets say we give as an input "aaa". Then we get the word "test" as an output in 3 seperate lines.
Now my question is, for the first letter that we type, 'a', does the program goes inside the while loop and remembers that it has to print something when the '\n' character is entered? Does it store the characters somewhere and then traverses them and executes the body of the while loop? Im lost.
There are many layers between the user writing input into a terminal, and your program receiving that input.
Typically the terminal itself have a buffer, which is flushed and sent to the operating system when the user presses the Enter key (together with a newline from the Enter key itself).
The operating system will have some internal buffers where the input is stored until the application reads it.
Then in your program the getchar function itself reads from stdin which is usually also buffered, and the characters returned by getchar are taken one by one from that stdin buffer.
And as mentioned in a comment to your question, note that getchar returns an int, which is really important if you ever want to compare what it returns against EOF (which is an int constant).
And you really should compare against EOF, otherwise you won't detect if there's an error or the user presses the "end-of-file" key sequence (Ctrl-D on POSIX systems like Linux or macOS, or Ctrl-Z on Windows).
What you see is due to the I/O line buffering.
The getchar() functions doesn't receive any input until you press the enter. This add the \n completing the line.
Only at this point the OS will start to feed characters to the getchar(), that for each input different from \n prints the test message.
Apparently the printout is done together after you press the enter.
You can change this behavior by modifying the buffering mode with the function setvbuf(). Setting the mode as _IONBF you can force the stream as unbuffered, giving back each character as it is pressed on the keyboard (or at least on an *nix system, MS is not so compliant).

why do we have to press ctrl-d while reading data from scanf?

scanf("%lf",&b);
fgets(str, 100, stdin);
In the above code, fgets is not read until I add a space after %lf (eg. scanf("%lf ",&b);),
or press ctrl-d instead of enter in the terminal. Why is this so?
Don't mix fgets() and scanf().
scanf() leaves a newline (when you press ENTER key) which terminates the input reading of fgets() as fgets() would as soon as it sees a newline character, effectively your fgets() not reading anything at all.
fgets():
fgets() reads in at most one less than size characters from stream
and stores them into the buffer pointed to by s. Reading stops after
an EOF or a newline. If a newline is read, it is stored into the
buffer. A terminating null byte ('\0') is stored after the last
character in the buffer.
When you have a whitespace in the format string (scanf("%lf ",&b);), the scanf call would only return after you input a non-whitespace which will then be read by the fgets() call. This approach is error-prone. Because you will be forced to input something if you don't read anything further.
Please see: Why does everyone say not to use scanf? What should I use instead?
The scanf("%lf",...) will stop and wait for more input when it encounters whitespace in input. Adding a space to the format string causes the whitespace character (or characters) to be removed from stdin, and the function to return.
Another way to cause scanf() to return is to make it recognise an error of some form. One way is to make it seem like it has reached end of file. You haven't mentioned it, but your host system is some flavour of unix - typing CTRL-D (depending on terminal settings you may need to hit CTRL-D after a newline, or possibly enter it twice) makes it seem like end of file has been encountered. If you check the return value from scanf() it will return EOF in this case too. Different systems require different actions to trigger end of file though.
Either way, fgets(..., stdin) cannot be called until scanf() returns. Note that triggering end of file may (depending on terminal settings) also cause fgets(..., stdin) to return EOF (i.e. it won't necessarily read input).
It is a really bad idea to mix use of scanf() (or related functions) and fgets() on the same stream (stdin in this case), because they do interact in strange ways (each relies on behaviour in interacting with the stream that the other doesn't provide)

End of File in stdin

A question about this has been asked here
End of File (EOF) in C
but it still doesn't completely solve my problem.
EOF makes sense to me in any datastream which is not stdin, for example if I have some data.txt file, fgetc() will read all the chars and come to the end of file and return -1.
What I don't understand is the concept of EOF in stdin. If I use getchar(), it will wait for me to enter something, so if there is NOTHING written, End of File, (EOF) is not returned automatically?
So is it that only the user can invoke EOF in stdin by pressing Ctrl+Z?
If so then what are some of the uses of EOF in stdin? I guess it tells the program to continue reading until the user invokes end of file? is this it?
Thank you
so if there is NOTHING written, End of File, (EOF) is not returned automatically?
No, it's not. It should be sent by the user.
So is it that only the user can invoke EOF in stdin by pressing Ctrl+Z?
Yes, you can set the EOF indicator for stdin with a special key combination you can input in the console, for linux console that is Ctrl+D and for windows it's Ctrl+Z.
If so then what are some of the uses of EOF in stdin? I guess it tells the program to continue reading until the user user invokes end of file? is this it?
The use of it depends on whether you instruct the user to input the EOF explicitly or not, for example, I think python console will tell you something like Press Ctrl+D or type quit() to exit.
And EOF is not necessarily -1 it's a macro and you should always use it to test for the EOF indicator. And more importantly EOF is not a character, it's a special value that indicates that the End Of File indicator is set.
Also, getchar() is equivalent to fgetc(stdin).
In linux bash, if you press CTRL+D, it will generate EOF.
In Windows, the equivalent is CTRL+Z
So, no, if nothing written to the terminal, that does not generate EOF automatically. The scanning function is in wait state then. So, without having any other inputs, in wait state, if CTRL+D is pressed, the key press is translated [by the terminal driver] to EOF.Note
Usually, once you key in some value and press the ENTER key, the scannning function starts scanning. To feed an input for producing EOF, you need to press CTRL+D.
Related: Please reaed the wiki entry for EOF
Note: With thanks to Mr Drew for the clarification.
stdin is a stream, data is not available until the user presses some keys. A file on the disk already has (a fixed amount of) content.
When reading from stdin, if getchar() doesn't wait for the user to input something then the program will always get EOF. That will make it impossible to use stdin as an input file.
Because getchar() waits for the user to input something there is no way to signal the input completed; that's why the operating systems provide a combination of keys that have this special meaning when they are pressed on the console.
Windows uses CtrlZ and Unix-like OSes (including OSX) use CtrlD for this purpose.
The file stdin is not always the user typing on the keyboard. If you redirect input to your program, it can be just a normal file.
program.exe <input-from-file.txt
What may be confusing you is that no giving input into a console window does not mark the end of the input. But think it the other way round: how could a user respond so quickly that the program would not terminate before it if the console would not do some buffering for the user? After pressing Enter the user says this is a line of input. In other words: a program running in a console window always waits for the next input to come.
Most programs define a special phrase to end a console session. You probably know exit.

Catching the EOF keystroke without pressing Enter C

I am writing a program which has a main menu, with a couple functions which I am allowing the user to access by typing in a number for one menu selections. For that, I am using _getch(). I need to be able to exit the program when the user enters the EOF key, but _getch() does not actually catch the EOF keystroke. I know I can get it to work by using getchar() instead of _getch(), but I would prefer not to have the user be forced to press enter after every function selection.
Is there a way to get _getch() to catch EOF? This is for Windows if it is of any importance, any help is really appreciated, as I have been unable to find anything out there.
The standard C input stream stdio is line buffered, and there is no defined way to forcibly flush it. If you want to avoid this and read from the buffer as every new character is entered, you have to use some OS specific magic, which is what _getch from conio.h tries to do.
There are other implementations out there of getch-type functions, for instance getch from the PDCurses library.

Read input from console in OSX

I'm using scanf() to read user input on terminal in a console application. scanf waits until the user hits the return key to read. Is there a way to read the user input on each keystroke?
The usual way would be to use the getch function from (the Mac port of) ncurses.
Note that while getchar reads a single character, it still normally does buffered reading, so you need to press 'return'/'enter' before it'll return.
getch() returns the character stream from stdin as it is typed.
char c = getchar();
It should do the trick.

Resources