getchar does not stop when using scanf - c

I have a difficulty understanding getchar(). In the following program getchar works as expected:
#include <stdio.h>
int main()
{
printf("Type Enter to continue...");
getchar();
return 0;
}
However, in the following program, getchar does not create a delay and the program ends:
#include <stdio.h>
int main()
{
char command[100];
scanf("%s", command );
printf("Type Enter to continue...");
getchar();
return 0;
}
I have the following weired workaround, which works, but I don't understand why:
#include <stdio.h>
int main()
{
char command[100];
int i;
scanf("%s", command );
printf("Type Enter to continue...");
while ( getchar() != '\n') {
i=0;
}
getchar();
return 0;
}
So my questions are:
1. What is scanf doing? Why does scanf do this ?
2. Why is my work around working?
3. What is a good way to emulate the following Python code:
raw_input("Type Enter to continue")

The input is only sent to the program after you typed a newline, but
scanf("%s", command );
leaves the newline in the input buffer, since the %s(1) format stops when the first whitespace character is encountered after some non-whitespace, getchar() then returns that newline immediately and doesn't need to wait for further input.
Your workaround works because it clears the newline from the input buffer before calling getchar() once more.
To emulate the behaviour, clear the input buffer before printing the message,
scanf("%s", command);
int c;
do {
c = getchar();
}while(c != '\n' && c != EOF);
if (c == EOF) {
// input stream ended, do something about it, exit perhaps
} else {
printf("Type Enter to continue\n");
getchar();
}
(1) Note that using %s in scanf is very unsafe, you should restrict the input to what your buffer can hold with a field-width, scanf("%99s", command) will read at most 99 (sizeof(command) - 1)) characters into command, leaving space for the 0-terminator.

Whitespace is a delimiter for 5y3 %s format specifier, and newline is regarded as whitespace, so it remains buffered. Console input is normally line oriented, so a subsequent call to getchar() will return immediately because a 'line' remains buffered.
scanf("%s", command );
while( getchar() != '\n' ){ /* flush to end of input line */ }
Equally if you use getchar() or %c to get a single character you normally need to flush the line, but in this case the character entered may itself be a newline so you need a slightly different solution:
scanf("%c", ch );
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
similarly for getchar():
ch = getchar();
while( ch != '\n' && getchar() != '\n' ){ /* flush to end of input line */ }
The sensible thing to do of course is to wrap these solutions into stand-alone specialised input functions that you can reuse and also use as a place to put common input validation and error checking code (as in Daniel Fischer's answer which sensibly checks for EOF - you would normally want to avoid having to duplicate those checks and error handling everywhere).

I'd rather first use fgets and then use sscanf to parse the input. I have been doing this stuff like this for a long time and the behaviour has been more predictable than using plain scanf.

Well, I have something easier: add another getchar() ... problem solved!!

after taking command input flush the stdin.
fflush(stdin);
but flushing a input stream results in undefined behavior (though Microsoft's C library defines the behaviour as an extension).

Related

Undefined behaviour of scanf() in a do-while loop

I'm currently learning C by a book "C Programming a modern approach" and encountered this code. When I tried to run it, after typing consecutive characters like 'abc' and hitting Enter (new line), nothing was printed. Please explain what is going on here.
char ch;
do {
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
You're asking the user to input a character using scanf. This is happening in a loop until the user inputs a '\n' or newline character (the same as pressing the enter key), which is when the loop will break.
Your print statement will then print the character in the variable ch, which at that point will be '\n' (since this variable just stores one character, the last one you typed).
This newline character will probably be invisible when you run your program so you may not be seeing it. You can add another print statement after the loop and if that print statement starts at a newline, you know that the '\n' was printed on the previous line.
Something like:
#include <stdio.h>
int main()
{
char ch;
do
{
scanf("%c" , &ch);
} while (ch != '\n');
printf("%c", ch);
printf("I should show up on a newline");
return 0;
}
The code you provided reads characters from the input using the scanf() function and stores them in the variable ch until a newline character (\n) is encountered. After that, the program prints the last character that was read, which is the newline character.
The reason you are not seeing any output when you enter characters followed by a newline character is because the printf() statement is only executed after the loop has finished running. So, the program is waiting for you to enter a newline character to terminate the loop and print the last character that was read.
If you want to see the characters you enter, you can add a printf() statement inside the loop, like this:
char ch;
do {
scanf("%c" , &ch);
printf("%c", ch);
} while (ch != '\n');
This will print out each character as it is read from the input, so you can see what you're typing. Happy coding :)
When I tried to run it, after typing consecutive characters like abc and hitting Enter (new line), nothing was printed.
Well with the posted code, if the loop even finishes, the last byte read by scanf("%c", &ch) and stored into ch is the newline character. Hence printf("%c", ch) outputs this newline and it seems nothing is printed but something is, the newline which is invisible on the terminal but does move the cursor to the next line.
You can make this more explicit by changing the printf call to this:
printf("last value: '%c'\n", ch);
Note however that the posted code is not a recommended way to read the contents of the input stream:
scanf("%c", &ch) may fail to read a byte if the stream is at end of file. Failure to test this condition leads to undefined behavior (ch is unmodified, hence stays uninitialized if the input stream is an empty file) or to an infinite loop as ch may never receive a newline.
this code is a typical example of a do / while with a classic bug. It would be much better to write the code using getchar() and a while loop.
Here is a modified version:
#include <stdio.h>
int main(void) {
int c; // must use int to distinguish EOF from all valid byte values
int count = 0; // to tell whether a byte was read at all
char ch = 0; // the last byte read
// read all bytes from the input stream until end of file or a newline
while ((c = getchar()) != EOF && c != '\n') {
ch = (char)c;
count++;
}
if (count == 0) {
printf("no characters entered: ");
if (c == EOF) {
printf("end of file or read error\n");
} else {
printf("empty line\n");
}
} else {
printf("last character on line is '%c'\n", ch);
if (c == EOF) {
printf("end of file or input error encountered\n");
}
}
return 0;
}

can't use 2 getchar() function in a simple C snippet code

I'm kind of noob at programming and specially in C lang. I'm trying some code to learn more about C syntax.here's my question: why the second getchar() in the bellow snippet code doesn't work? I mean I want to console wait till I Enter and then finish.
#include<stdio.h>
#include<curses.h>
int main() {
char ch = getchar();
getchar();
return 0;
}
PS: I use ubuntu 17.10.
As mentioned in the comments, you are typing two characters. Letter a and the new line character(\n). show second getchar() accept \n.
If you want to use second getchar() then before using it use fflush(stdin).
fflush(stdin) normally deletes (flushes) this type of extra character (in your case \n). or you can do as below
#include<stdio.h>
#include<curses.h>
int main() {
char ch;
printf("Enter a charcter: ");
ch = getchar();
printf("\nyou typed the character ");
putchar(ch);
while ((getchar()) != '\n'); //fflush(stdin); /* use this*/
getchar();
return 0;
}
Here “while ((getchar()) != ‘\n’);” reads the buffer characters till the end and discards them(including newline) and using it after the “scanf()” statement clears the input buffer and allows the input in the desired container.
And also see the following links.
Replacement of fflush(stdin)
Alternative to C library-function fflush(stdin)
Using fflush(stdin)
Clearing The Input Buffer In C/C++

While loop in C don't break even after encountering a NULL character

here is the code to add the numbers present in an Alphanumeric string :
#include<stdio.h>
#include<stdlib.h>
int main()
{
int total=0;
char ch;
printf("enter the string\n");
ch=getchar();
while(ch!='\0')
{
printf("I am here !!");
if (!(isalpha(ch)))
total+=(int)ch;
ch=(char)getchar();
printf("I am here !!");
}
printf("\ntotal is %d",total);
return 0;
}
No matter what characters I input , it gives 4 " I am here " for each character.
I tried to use
while((ch=getchar())!='\0');
but it gives the same problem .
getchar does not return '\0' at the end of the input: it is not reading from a null-terminated C string, but from a console, file, or some other stream.
When no additional input is available, getchar returns EOF. That is the condition you should be checking to decide when to stop your loop.
Stack Overflow offers many good examples of how to implement a loop reading getchar (link#1; link#2; please note the data types used in the examples).
The reason it doesn't work is because '\0' cannot be inserted from the keyboard, so getchar() is unlikely to be able to return '\0', a correct way of testing for the end of input would be
int ch;
while (((ch = getchar()) != EOF) && (ch != '\n'))
This is because EOF means, that the user intentionally wanted to stop entering data, and '\n' is usually the last thing that will be seen when stdin is flushed, since it triggers the flushing.

GETS - C is not working for me

I am having trouble with inserting string in to char variable. Problem appeares when I put it into function. When I debug my program, it displays printf but it skipes gets
here is my code:
int uloz(SPRAVA *p){
char string[200];
printf("Your message here: ");
gets(string);
printf("You have entered: %s", string);
getchar();
return 0;
}
Use scanf(" %30[^\n]%*c",string);
[^\n] will accept anything till \n.
30 will limit the length of number of characters to max 30.
initial space(' ') will consume any \n already in stdin stream. (optional & i have not verified it)
& Finally, %*c will consume \n pressed after entering string.
I think, scanf(" %30[^\n]%*[^\n]%*c",string); would be a good option, to discard remaining characters (after 30) that were entered. However this is completely unverified. Just added as a possible idea. Test before use. :-)
There's a newline in the stdio buffer (left over by some previous scanf) so gets is immediately satisfied.
There's no easy way to fix it but you could try discarding input, before the fgets:
while((c = getchar()) != '\n' && c != EOF)
/* discard the character */;
The true solution is to avoid mixing scanf and fgets.
Use fgets instead of gets.

get user input (terminate by enter key)

i use a scanf to get user input but if i press enter, the cursor will flash to next line~
what function should i use instead of scanf if i want the program will terminated if the users only press enter without keying any thing?
thanks
Scanf reads until the next token -- it doesn't really care about newlines at all (just considers them to be whitespace, like spaces or tabs).
Instead, use a line-reading function like fgets.
you can use gets() function in this way :
#include <stdio.h>
#define MAX_INPUT_CHAR 100
int main( ) {
char str[MAX_INPUT_CHAR ];
printf( "Enter a value :");
gets( str );
return 0;
}
Function char *gets(char *s) reads a line from stdin into the buffer pointed to by
s until either a terminating newline or EOF (End of File)
Pay attention gets() is not safe. You can't now apriori how much character it will read. This can cause some security problem and eventually crash.
Just use this code :
char ch;
printf("Enter Your Sentence \n");
while (1)
{
ch = getch();
if ((int)ch == 13)
break;
printf("%c", ch);
}
I disagree:
char * x;
scanf("%s",x);
printf("Inserted line: %s\n",x);
Will store in x only the characters till the return key.
I build it and runned it and it works.

Resources