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().
Related
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I have this block of code (functions omitted as the logic is part of a homework assignment):
#include <stdio.h>
int main()
{
char c = 'q';
int size;
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("Length:");
scanf("%d",&size);
while(c!='q')
{
switch(c)
{
case 'l': line(size); break;
case 's': square(size); break;
case 't': triangle(size); break;
}
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("\nLength:");
scanf("%d",&size);
}
return 0;
}
The first two Scanf's work great, no problem once we get into the while loop, I have a problem where, when you are supposed to be prompted to enter a new shape char, it instead jumps down to the printf of Length and waits to take input from there for a char, then later a decimal on the next iteration of the loop.
Preloop iteration:
Scanf: Shape. Works Great
Scanf: Length. No Problem
Loop 1.
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the shape char.
Loop 2
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the size int now.
Why is it doing this?
scanf("%c") reads the newline character from the ENTER key.
When you type let's say 15, you type a 1, a 5 and then press the ENTER key. So there are now three characters in the input buffer. scanf("%d") reads the 1 and the 5, interpreting them as the number 15, but the newline character is still in the input buffer. The scanf("%c") will immediately read this newline character, and the program will then go on to the next scanf("%d"), and wait for you to enter a number.
The usual advice is to read entire lines of input with fgets, and interpret the content of each line in a separate step. A simpler solution to your immediate problem is to add a getchar() after each scanf("%d").
The basic problem is that scanf() leaves the newline after the number in the buffer, and then reads it with %c on the next pass. Actually, this is a good demonstration of why I don't use scanf(); I use a line reader (fgets(), for example) and sscanf(). It is easier to control.
You can probably rescue it by using " %c" instead of "%c" for the format string. The blank causes scanf() to skip white space (including newlines) before reading the character.
But it will be easier in the long run to give up scanf() and fscanf() and use fgets() or equivalent plus sscanf(). All else apart, error reporting is much easier when you have the whole string to work with, not the driblets left behind by scanf() after it fails.
You should also, always, check that you get a value converted from scanf(). Input fails — routinely and horribly. Don't let it wreck your program because you didn't check.
Try adding a space in the scanf.
scanf(" %d", &var);
// ^
// there
This will cause scanf() to discard all whitespace before matching an integer.
Use the function
void seek_to_next_line( void )
{
int c;
while( (c = fgetc( stdin )) != EOF && c != '\n' );
}
to clear out your input buffer.
The '\n' character is still left on the input stream after the first call to scanf is completed, so the second call to scanf() reads it in. Use getchar().
When you type the shape and ENTER, the shape is consumed by the first scanf, but the ENTER is not! The second scanf expects a number so, the ENTER is skipped because is considered a white space, and the scanf waits for a valid input ( a number) that, again, is terminated by the ENTER. Well, the number is consumed, but the ENTER is not, so the first scanf inside the while uses it and your shape prompt is skipped... this process repeats. You have to add another %c in the scanfs to deal with the ENTER key. I hope this helps!
You can also use
scanf("%c%*c", &c);
to read two characters and ignore the last one (in this case '\n')
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;.
normally, strlen() does not count the null terminator at the end of the string. But, below code prints the string count with the null terminator. Can anyone explain me why? Thanks
char str2[100];
printf("\nEnter a string: ");
fgets (str2, sizeof(str2), stdin);
printf("\n%d",strlen(str2));
I am assuming the preceding fgets prompt picked up the newline character.
For example:
You put in apple.
Internally your string was stored as apple\n\0.
strlen then returned 6 for apple + '\n'
The fgets() function accepts the input when a newline character(Enter key when using stdin) is encountered, and the newline character \n is considered a valid character by the function and included in the string copied to your str2.Hence when you pass it as a parameter to strlen() it gives one more than the original number of characters in your string to account for the additional \n character.
If you want the original number of characters or don't want a \n to be added, use the gets() function as it doesn't copy the newline character.And further, you only need to pass the string as argument,no need to pass the stream (stdin) as the default stream for gets() is stdin.
char str2[100];
printf("\nEnter a string: ");
gets(str2);
printf("\n%d",strlen(str2));
Here you have used fgets() function to take input. When you take input by fgets() function then an additional new line character('\n') will be added with your sting. suppose your input is : "hello" . after typing this sting you must press ENTER key for which new line character will be added with your string. Hence its seems to you that strlen() counts the null terminator. But if you take input using scanf() function it will not add additional new line character('\n') when ENTER is pressed. So you will see the exact number of character you string contains. Run the following code to see my explanation.
#include<stdio.h>
#include<string.h>
void main()
{
char str2[100];
printf("\nEnter a string: ");
scanf("%s",str2);
//fgets (str2, sizeof(str2), stdin);
printf("\n%d",strlen(str2));
}
as stated by others, the fgets() will read the newline(\n) character and store it in your array.
after every call to fgets() I always use strcspn() to search the array/pointer to find the newline character and replace it with the null character.
char str2[100];
printf("\nEnter a string: ");
fgets (str2, sizeof(str2), stdin);
//new line of code to replace '\n' with '\0'
str2[strcspn(str2, "\n")] = '\0';
printf("\n%d",strlen(str2));
fgets() reads until \n is encountered.
If the user enters anshul then str2 will contain anshul\n\0.
strlen() will return 7 because strlen() searches until it finds the NULL('\0') character.
gets(s) does not include the '\n' when you hit the enter key after being done entering the string.But, fgets() does include the '\n' while reading from a file.
As per the man page(use: man fgets) on linux terminal,
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.
This question already has answers here:
scanf() leaves the newline character in the buffer
(7 answers)
Closed 6 years ago.
I have this block of code (functions omitted as the logic is part of a homework assignment):
#include <stdio.h>
int main()
{
char c = 'q';
int size;
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("Length:");
scanf("%d",&size);
while(c!='q')
{
switch(c)
{
case 'l': line(size); break;
case 's': square(size); break;
case 't': triangle(size); break;
}
printf("\nShape (l/s/t):");
scanf("%c",&c);
printf("\nLength:");
scanf("%d",&size);
}
return 0;
}
The first two Scanf's work great, no problem once we get into the while loop, I have a problem where, when you are supposed to be prompted to enter a new shape char, it instead jumps down to the printf of Length and waits to take input from there for a char, then later a decimal on the next iteration of the loop.
Preloop iteration:
Scanf: Shape. Works Great
Scanf: Length. No Problem
Loop 1.
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the shape char.
Loop 2
Scanf: Shape. Skips over this
Scanf: length. Problem, this scanf maps to the size int now.
Why is it doing this?
scanf("%c") reads the newline character from the ENTER key.
When you type let's say 15, you type a 1, a 5 and then press the ENTER key. So there are now three characters in the input buffer. scanf("%d") reads the 1 and the 5, interpreting them as the number 15, but the newline character is still in the input buffer. The scanf("%c") will immediately read this newline character, and the program will then go on to the next scanf("%d"), and wait for you to enter a number.
The usual advice is to read entire lines of input with fgets, and interpret the content of each line in a separate step. A simpler solution to your immediate problem is to add a getchar() after each scanf("%d").
The basic problem is that scanf() leaves the newline after the number in the buffer, and then reads it with %c on the next pass. Actually, this is a good demonstration of why I don't use scanf(); I use a line reader (fgets(), for example) and sscanf(). It is easier to control.
You can probably rescue it by using " %c" instead of "%c" for the format string. The blank causes scanf() to skip white space (including newlines) before reading the character.
But it will be easier in the long run to give up scanf() and fscanf() and use fgets() or equivalent plus sscanf(). All else apart, error reporting is much easier when you have the whole string to work with, not the driblets left behind by scanf() after it fails.
You should also, always, check that you get a value converted from scanf(). Input fails — routinely and horribly. Don't let it wreck your program because you didn't check.
Try adding a space in the scanf.
scanf(" %d", &var);
// ^
// there
This will cause scanf() to discard all whitespace before matching an integer.
Use the function
void seek_to_next_line( void )
{
int c;
while( (c = fgetc( stdin )) != EOF && c != '\n' );
}
to clear out your input buffer.
The '\n' character is still left on the input stream after the first call to scanf is completed, so the second call to scanf() reads it in. Use getchar().
When you type the shape and ENTER, the shape is consumed by the first scanf, but the ENTER is not! The second scanf expects a number so, the ENTER is skipped because is considered a white space, and the scanf waits for a valid input ( a number) that, again, is terminated by the ENTER. Well, the number is consumed, but the ENTER is not, so the first scanf inside the while uses it and your shape prompt is skipped... this process repeats. You have to add another %c in the scanfs to deal with the ENTER key. I hope this helps!
You can also use
scanf("%c%*c", &c);
to read two characters and ignore the last one (in this case '\n')
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.