I have often seen cases where in a series of printf statements that ask for an input, certain
statements do not accept an input, i.e.
printf_statement1:
printf_statement2: /*Enter input here*/
i.e. before the user enters an input for statement1, statement2 is printed, that allows the user to enter an input, and then repeats the same with statement3 & statement4.
What prompts such a case?
I encounterd this, but not any more, in:
printf("\n\n\t\tName: ");
scanf("%s", name); //initially used gets
printf("\n\n\t\tType: ");
scanf("%c", &type);
printf("\n\n\t\tAddress: "); //initially used gets
scanf("%s", address);
printf("\n\n\t\tDate - of - Birth: ");
scanf("%s", dob); //initially used gets
Output:
Name:
Type: I enter something!
Address:
Date - of - Birth: I enter something!
I know this question is already marked as answered, but as fflush(stdin) makes me cringe I wanted to post an alternative to clearing stdin:
void clear_stdin(void)
{
int c;
do {
c = fgetc(stdin);
} while (c != '\n' && c != EOF);
}
This will clear any chars up until a new line or until EOF is encountered. (You could just stick the body and condition of the do..while into the condition of a while loop, but I prefer to write it that way.)
It'd be useful to call that function for example after wanting to read in a single char, to prevent subsequent prompts from seeming to be skipped if the user enters more than 1 character.
Also consider using fgets() or providing a width specifier with scanf() in order to prevent overflows.
to replace fflush(stdin) in "Jonathon Reinhart" answer , i suggest this function, which is standard compliant :
void clean_stdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
The root of the problem is that the "%c" conversion specifier doesn't skip over whitespace. Suppose you type "Joe" for the name; the input stream will contain the characters 'J', 'o', 'e', '\n'. The first call to scanf looks for a string ("%s" conversion specifier); it will consume 'J', 'o', and 'e', and leave the '\n' in the input stream. In response to the next prompt, you type a character like 'A', so the input stream now contains '\n', 'A', '\n'. The next call to scanf looks for a single character; it will consume the first newline and return, leaving 'A' and '\n' in the input stream.
Rather than flushing stdin (which is not a well-defined operation according to the language definition), it's better to avoid using the "%c" conversion specifier for interactive input; frankly, it's better to avoid using scanf for interactive input and use fgets instead.
A quick and dirty solution would be to change the type of type from a simple char to an array of char and read it as a string:
char type[2];
...
fgets(type, sizeof type, stdin);
This will skip over any newlines stuck in the input stream without having to flush anything. Then you'd just use type[0] for your type value.
Edit
If you don't want to change the type of type, you can do something like this:
#include <ctype.h>
...
while ((type = fgetc(stdin)) && isspace(type))
;
which will read individual characters from stdin until it sees a non-whitespace character.
Sometimes in cases like these, it is helpful to call fflush() on stdin before reading from it:
char name[40+1];
printf("\n\tName: ");
fflush(stdin);
scanf("%40s", name);
Depending on the circumstances, there may be a newline in the input buffer that causes your first scanf to get skipped (given no input).
Also note that you should specify the size of the buffer in scanf as to avoid buffer overflows.
A format specifier for scanf looks like this:
%[*][width][modifiers]type
width: Specifies the maximum number of characters to be read in the current reading operation
Thus, the %40s specifies that only 40 characters may be read in to the string. Note that the buffer is 41 characters, leaving room for the NULL terminator.
Edit: Some sources (like this and this) say that you should avoid calling fflush(stdin) and it is incorrect. However, the Linux man page states:
For input streams, fflush() discards any buffered data that has been fetched from the underlying file, but has not been consumed by the application.
Conforming to C89, C99, POSIX.1-2001, POSIX.1-2008.
The standards do not specify the behavior for input streams. Most other implementations behave the same as Linux.
Additionally: MSDN says nothing about calling fflush(stdin) other than the following:
If the stream is open for input, fflush clears the contents of the buffer.
One would think that if calling fflush(stdin) was such a problem, one of the two largest sources of documentation on fflush would have mentioned this.
Related
The following code produces a very strange result when I run it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for ( ; ; )
{
char test;
printf("Please enter 'w' ");
scanf("%c", &test);
printf("%c\n", test);
if (test == 'w')
{
printf("Working\n");
}
else
{
printf("ERROR\n");
return 0;
}
}
}
What I want to happen is for the whenever I input 'w' it continues the loop so I can input 'w' again. What it does though is go to the else statement even though I input 'w'. It just seems to skip the scanf() line. I have asked everyone I know who knows C but they do not know how to solve it.
Somebody please help me out here!
This is because you type w followed by ENTER. So there are 2 characters in the input, 'w', followed by a newline (\n). The latter causes the else branch to be taken on the second iteration.
Note that standard input is line buffered when connected to a terminal. If you need to deal with characters immediately, there are ways to do that. See the comp.lang.c FAQ for details ("How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?").
Note that for robust programming it is a must to check the return value of scanf. It returns the number of successfully converted items. As shown, your code does not handle the case of end-of-file properly, i.e. when the user types Ctrl-D (assuming Unix terminal). Then scanf returns EOF and no conversion was performed, but you use test as if it contained a meaningful value.
as Jens said. you have to ignore the newline '\n'
Adding a space at the beginning of the format specifier " %c" will ignore the newline '\n'
scanf(" %c", &test);
Using " %c" will also ignore other white spaces like \t space \b \v \r
As Jens says, you must consume '\n', use getchar() after scanf()
You need to do something like
scanf("%c", &test);
while(getchar()!='\n');
scanf takes input upto space or \n (whichever comes first) and leaves the \n in the buffer
I'm trying to store two characters in two different chars using fgets().
char tobereplaced[1], replacedwith[1];
printf("Please enter character to be replaced\n");
fflush(stdin);
fgets(tobereplaced, 2, stdin);
printf("Please enter character to replace with\n");
fflush(stdin);
fgets(replacedwith, 2, stdin);
printf("User asks to replace \'%s\' with \'%s\'\n", tobereplaced, replacedwith);
If i enter 'a' and 'b' I get the following output:
User asks to replace '' with 'b'
So my question is why is only the second value getting stored and the first one isnt?
Note, I am using "2" as the second argument in fgets() because if I use "1" (which to me seems like the obvious value) it doesnt stop and wait for input for some reason.
fgets() attempts to read a line of input (all characters up to and including a '\n'). Then it appends a null character.
With input aEnter, fgets() would like at least a tobereplaced[3] array to store store the 'a', '\n', '\0',
The following code is bad as it incorrectly told fgets() there was 2 char available in tobereplaced[]
char tobereplaced[1]; // Only 1
fgets(tobereplaced, 2, stdin); // bad, UB, said it was 2
Instead, to read a line, with extra space in case the user enters some extra characters:
char tobereplaced[80];
fgets(tobereplaced, sizeof tobereplaced, stdin);
printf("Please enter character to replace with\n");
char replacedwith[80];
fgets(tobereplaced, sizeof tobereplaced, stdin);
printf("User asks to replace \'%c\' with \'%c\'\n", tobereplaced[0], replacedwith[0]);
Regarding the fflush(stdin). If I remove then the fgets won't stop and wait for input. How can I solve this problem without using the fflush? Or am I missing something crucial here?
Certainly due to using a prior scanf() which left a '\n' in stdin. fgets() did not have to stop and wait for input as there was left-over '\n' in stdin to be read. fflush(stdin) is undefined behavior.
I recommend to use only fgets() for user input.
Do not use scanf() until you understand why its bad.
The function fgets stores a C string, witch is terminated by a null char, or '\0', you need space to store this char or it will work unexpectedly. In your case, simply change the array size to 2 or use a function like getchar().
The following code produces a very strange result when I run it.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for ( ; ; )
{
char test;
printf("Please enter 'w' ");
scanf("%c", &test);
printf("%c\n", test);
if (test == 'w')
{
printf("Working\n");
}
else
{
printf("ERROR\n");
return 0;
}
}
}
What I want to happen is for the whenever I input 'w' it continues the loop so I can input 'w' again. What it does though is go to the else statement even though I input 'w'. It just seems to skip the scanf() line. I have asked everyone I know who knows C but they do not know how to solve it.
Somebody please help me out here!
This is because you type w followed by ENTER. So there are 2 characters in the input, 'w', followed by a newline (\n). The latter causes the else branch to be taken on the second iteration.
Note that standard input is line buffered when connected to a terminal. If you need to deal with characters immediately, there are ways to do that. See the comp.lang.c FAQ for details ("How can I read a single character from the keyboard without waiting for the RETURN key? How can I stop characters from being echoed on the screen as they're typed?").
Note that for robust programming it is a must to check the return value of scanf. It returns the number of successfully converted items. As shown, your code does not handle the case of end-of-file properly, i.e. when the user types Ctrl-D (assuming Unix terminal). Then scanf returns EOF and no conversion was performed, but you use test as if it contained a meaningful value.
as Jens said. you have to ignore the newline '\n'
Adding a space at the beginning of the format specifier " %c" will ignore the newline '\n'
scanf(" %c", &test);
Using " %c" will also ignore other white spaces like \t space \b \v \r
As Jens says, you must consume '\n', use getchar() after scanf()
You need to do something like
scanf("%c", &test);
while(getchar()!='\n');
scanf takes input upto space or \n (whichever comes first) and leaves the \n in the buffer
I was always bad at inputting characters in C and this is another example. Though I understood (maybe) what's happening but I can't figure out the solution.
I have the following code
scanf("%ld %ld",&n,&m);
for(i=0;i<n;i++)
scanf("%ld",&array[i]);
for(i=0;i<m;i++)
{
fflush(stdin);
//inputting a character 'R' but it is picking '\n' from past buffer
scanf("%c",&query);
//As a result of above problem, it is also acting wierd for same reason
scanf("%ld",&d);
printf("%c %ld",query,d);
printf("\nI=%ld\n",i);
}
Please help me figure out the reason why its happening and what is the solution.
Using scanf with %d (or %ld) only extracts the number from the input stream; it leaves the newline in the stream.
So when you write scanf("%c", it reads that newline.
To fix this (if your intent is that scanf("%c" reads the first character of the next line), you need to flush the input of the previous line. One way to do that is:
int ch; while ( (ch == getchar()) != EOF && ch != '\n' ) { }
Your line fflush(stdin); causes undefined behaviour - don't do that. The fflush function is only for output streams.
Also , it is a really good idea to check the return value of scanf. If it was not what you expected then you may wish to take some action, instead of pretending that a number was entered.
Since you are tired of input issues, I can give you a method that can help to simplify your live.
I can observe that:
You have problems in handling end-of-lines.
Sometimes you need to input numbers and sometimes you need characters or another kind of input. So, you (think that you) are forced to use formatted input.
My advice is that you separate the issue of reading input from the issue of interpreting data entered from input.
The standard C brings only a few functions to handle input/output operations, in the standard header <stdio.h>.
If you are not interested in very sofisticated I/O results, the standard library is enough.
However, the functions of <stdio.h> usually have the effect that input is read one line at the time, which includes the end-of-line character: '\n'.
What you can do, then, it's what follows:
Read a line with fgets(..., stdin) and put the result in a buffer (not so long), used only for this purpose.
Once you have read an entire line, no more issues with end-of-line will bother you.
Then, re-read this line, that it's held in a buffer, and apply to it all the formatted input that you need.
A short example:
#include <stdio.h>
int main(void) {
char buffer[200] = ""; // Initialize array to 0's
long int n, m;
char c;
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%ld %ld",&n,&m);
// Now you have processed the "integer number" input,
// read input characters again, withou any "flushes" and extrange things:
fgets(buffer, sizeof(buffer), stdin);
sscanf(buffer,"%c", &c);
fgets(buffer, sizeof(buffer), stdin);
// and so on...
}
Thus, every time you need to separate a section of input from a previous one, just do a new line reading with fgets(..., stdin), which stores the input in buffer, and then process the buffer with sscanf(), which applies the format string to the buffer instead of the input itself (in its flesh).
Note: This method can have a little problem: If the string input has more than sizeof(buffer) characters (in the example: 200), the line is not completely read. This situation can be handled by checking if the character before last in buffer is not equal to '\n' nor '\0'. In such a case, you would make automatically some kind of "flushing input" operation (reading and discarding characters till the next end-of-line is found).
I'm trying to use gets() to get a string from the user, but the program seems to be passing right over gets(). There is no pause for the user to give input. Why is gets() not doing anything?
char name[13];
printf("Profile name: ");
gets(name);
printf("\n%s", name);
Call getchar() before you call gets() or fgets(). Since gets() or fgets() is getting skipped due to an already present '\n' from previous inputs in stdin, calling getchar() would lead to itself getting skipped instead of gets() or fgets() or any other similar function. But remember its more of a hack and not a standard solution (I think so), and also use of gets() is forbidden.
printf("\nEnter a String: ");
getchar();
//fgets(inputString, 100, stdin);
gets(inputString);
printf("\n%s", inputString);
It's because gets() it's so incredibly dangerous to use, that some C libraries have removed it completely and replaced it with a version that does nothing.
Use fgets() instead.
Use fflush(stdin); before gets()
You get lot of troubles using gets()
Instead go for fgets()
fgets(name,13,stdin);
See this SO question Why is the gets function so dangerous that it should not be used?
The reason why fgets() does not work, may be you are not handling the newline left behind by scanf in your previous statements.
You can modify your scanf format string to take it into account:
scanf("%d *[^\n]", &N);
*[^\n] says to ignore everything after your integer input that isn't a newline, but don't do anything with the newline (skip it).
When you use scanf("%d",&num) you hit 13 and enter and 13 is stored in num and the newline character is still in the input buffer when you read fgets from stdin it treats \n as the data you have entered and the fgets() statement is skipped
You cannot flush input buffer however you can do this fseek(stdin,0,SEEK_END); add this before your every fgets statement
Take a look at gets() reference
Get string from stdin
Reads characters from the standard input (stdin) and stores them as a C string into str until a newline character or the end-of-file is reached.
The newline character, if found, is not copied into str.
A terminating null character is automatically appended after the characters copied to str.
Notice that gets is quite different from fgets: not only gets uses stdin as source, but it does not include the ending newline character in the resulting string and does not allow to specify a maximum size for str (which can lead to buffer overflows).
So, basically gets() is not only unsafe (can lead to buffer overflows) but also reads what's in the input buffer.
I recommend you to use fgets(), but if you want a quick (and lazy and stupid) solution, just flush the input buffer:
char name[13];
printf("Profile name: ");
fflush(stdin);
gets(name);
printf("\n%s", name);
Add this below function to your code and enjoy it.
string GetString()
{
char ch;
string Line="";
while(1)
{
ch=getchar();
if(ch=='\n')
break;
else
Line+=ch;
}
return Line;
}
This function can effect all Spaces and Backspaces too!!!
You might need to discard the rest of the line and move on to the beginning of the next one. You can do:
int c; while((c=getchar()) != '\n' && c != EOF);
This discards the rest of the current line (which might have been partially read with scanf(), etc.) and moves on to the next one.
Although fflush(stdin) might also discard the input, it is non-standard behaviour and discouraged.
You should never ever use gets(myString), as it has been completely removed from the C standard due to how unsafe it is. It doesn't enforce the length of the string, so you can go past the end of the buffer and overwrite other values in RAM, causing a buffer overflow, which can be a security vulnerability. Use fgets(myString, myStringSize, stdin); instead. To get rid of the newline in the resulting string, use myString[strcspn(myString, "\n")] = 0;.