Reading newline from previous input when reading from keyboard with scanf()
Solution 1
First scanf
read the entered string and left behind \n
in the input buffer. Next call to scanf
read that \n
and store it to character
.
Try this
scanf (" %c", &characte);
// ^A space before %c in scanf can skip any number of white space characters.
Program will not work for strings more than one character because scanf
stops reading once find a white space character. You can use fgets
instead
fgets(string, 200, stdin);
Solution 2
OP's first problem is typically solved by prepending a space to the format. This will consume white-space including the previous line's '\n'
.
// scanf("%c", &character);
scanf(" %c", &character);
Moreover, the program does not work for strings with more than one word. How could I overcome these problems?
For the the 2nd issue, let us go for a more precise understanding of "string" and what "%s"
does.
A string is a contiguous sequence of characters terminated by and including the first null character. 7.1.1 1
OP is not entering a string even though "I enter a string (e.g.: computer)," is reported. OP is entering a line of text. 8 characters "computer" followed by Enter. There is no "null character" here. Instead 9 char
"computer\n"
.
"%s"
in scanf("%s", string);
does 3 things:
1) Scan, but not save any leading white-space.
2) Scan and save into string
any number of non-white-space.
3) Stop scanning when white-space or EOF reached. That char
is but back into stdin
. A '\0'
is appended to string
making that char
array a C string.
To read a line including spaces, do not use scanf("%s",...
. Consider fgets()
.
fgets(string, sizeof string, stdin);
// remove potential trailing \r\n as needed
string[strcspn(string, "\n")] = 0;
Mixing scanf()
and fgets()
is a problem as calls like scanf("%s", string); fgets(...)
leave the '\n'
in stdin
for fgets()
to read as a line consisting of only "\n"
. Recommend instead to read all user input using fgets()
(or getline()
on *nix system). Then parse the line read.
fgets(string, sizeof string, stdin);
scanf(string, "%c", &character);
If code must user scanf()
to read user input including spaces:
scanf("%*[\n]"); // read any number of \n and not save.
// Read up to 199 `char`, none of which are \n
if (scanf("%199[^\n]", string) != 1) Handle_EOF();
Lastly, code should employ error checking and input width limitations. Test the return values of all input functions.
Solution 3
What you're seeing is the correct behavior of the functions you call:
scanf will read one word from the input, and leave the input pointer immediately after the word it reads. If you type
computer<RETURN>
, the next character to be read is the newline.To read a whole line, including the final newline, use
fgets
. Read the documentation carefully:fgets
returns a string that includes the final newline it read. (gets
, which shouldn't be used anyway for a number of reasons, reads and discards the final newline.)
I should add that while scanf
has its uses, using it interactively leads to very confusing behavior, as I think you discovered. Even in cases where you want to read word by word, use another method if the intended use is interactive.
Solution 4
You can make use of %*c
:
#include <string.h>
#include <stdio.h>
int main()
{
char string[200];
char character;
printf ("write something: ");
scanf ("%s%*c", string);
printf ("%s", string);
printf ("\nwrite a character: ");
scanf ("%c%*c", &character);
printf ("\nCharacter %c Correspondent number: %d\n", character, character);
return 0;
}
%*c
will accept and ignore the newline or any white-spaces
Related videos on Youtube
El Cid
Updated on September 17, 2022Comments
-
El Cid over 1 year
This was supposed to be very simple, but I'm having trouble to read successive inputs from the keyboard.
Here's the code:
#include <string.h> #include <stdio.h> int main() { char string[200]; char character; printf ("write something: "); scanf ("%s", string); printf ("%s", string); printf ("\nwrite a character: "); scanf ("%c", &character); printf ("\nCharacter %c Correspondent number: %d\n", character, character); return 0; }
What is happening
When I enter a string (e.g.: computer), the program reads the newline (
'\n'
) and puts it incharacter
. Here is how the display looks like:write something: computer computer Character: Correspondent number: 10
Moreover, the program does not work for strings with more than one word. How could I overcome these problems?
-
John almost 9 years
scanf
is insecure, usefgets
instead. -
ericbn almost 9 yearspossible duplicate of Why Scanf works wierd while taking a character
-
ericbn almost 9 years@ElCid, sure! meta.stackoverflow.com/questions/252929/…
-
user3629249 almost 9 yearsregarding this line: 'scanf ("%s", string);' the user could overflow the input buffer, resulting in undefined behaviour and leading to a seg fault event. suggest: 'scanf ("%199s", string);'
-
-
chux - Reinstate Monica almost 9 yearsNote:
%*c
will accept and ignore any followingchar
which is often the newline, but could be any white-space like' '
. -
Jahid almost 9 years@ chux, Yes, that's right. I will add your note to my answer precisely.
-
chux - Reinstate Monica almost 9 yearsOP's use of
printf()
is correct. Variadic arguments likechar character
are promoted using the usual proportion toint
(or rarelyunsigned
) so the castint
is not needed.printf ("%c %d",...
takes twoint
arguments so OP is using the correct specifier. "d,i Theint
argument is converted ..." "c If no l length modifier is present, theint
argument... " C11 §7.21.6.1 8 -
user3629249 almost 9 yearsI agree with using fgets() rather than scanf() to read a line of text. However, the second input is expected to input the 'newline' and 'newline' is white space, so the suggested: scanf (" c", &character); will not work as scanf will skip over the new line. Maybe that is what is wanted, the question was unclear on that detail.
-
haccks almost 9 years@user3629249; It is always safe to use
" %c"
inscanf
. What if user will press Enter/Return twice? -
M.M about 7 yearsYour code has a buffer overflow, and
fflush(stdin)
causes undefined behaviour -
M.M about 7 yearsThis has a buffer overflow; you need to limit the input
-
ps_ about 7 years@M.M any evidence to back up the fact that fflush produces undefined behaviour ! And I didn't quite get the buffer overflow part can you please rephrase/explain. Thanks.
-
M.M about 7 yearsIf they type 200 letters then you overflow
string
. Forfflush
see section 7.21.5.2/2 of the current C standard, "If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined".stdin
is not an output or update stream. -
ps_ about 7 years@M.M As far as buffer overflow goes, that's not the point I was trying to make. Obviously an array would overflow if you try storing data beyond its capacity. I was neither addressing that issue nor trying to accommodate for that in my code.
-
ps_ about 7 years@M.M And yes the specification says so, but still
fflush
is behaving entirely as one would predict and as is supposed to even with an input stream hence I think it'd be safe to assume thatstdin
can be flushed in this manner without any repercussions unless you've a counter example where flushing stdin between successive inputs results in undefined behaviour. Also I amn't quite aware of the term update stream, can you please tell me what exactly does it mean, and what's exactly the difference between an input stream and an update stream. Thanks. -
M.M about 7 yearsfflush isn't behaving as I would predict and it is not supposed to do some particular thing for an input stream. You are mistakenly assuming that behaviour you observed on one compiler is standard behaviour. "update stream" means one that can be used for reading and writing (opened with
+
flag) -
ps_ about 7 years@M.M I understand what you are trying to point out. Can you please give me a compiler version and a corresponding environment and a particular program where
fflush
goes haywire. It's just that I want to see it for myself how exactly things go in that case. Also, you say "it isn't supposed to do some particular things for an input stream...", what all is it not supposed to do that it's doing here, can you please be more specific ? All that's visible in the foreground is that it flushed the extra characters present in the stream which I feel is acceptable, correct me if I am wrong. Thanks. -
M.M about 7 yearsSee what is undefined behaviour. There is no defined behaviour for fflush on an input stream. You still do not seem to understand this. You could google "fflush stdin does not work" for examples of people who had similar misgivings to yourself, and see what systems they were on.
-
ps_ about 7 yearsGot it! Thanks ! Peace out.