I'm doing homework that asks me to read an integer n
representing the size of a loop and then read a line of characters n
times and print it right after the user's input. So I used scanf
and then I print it with printf
. The problem is that if the user's input is only a newline character, it should print another \n
, but scanf
seems to ignore the input when it's a single \n
.
Is there any way to make this assignment with scanf
or should I try something else?
int i;
scanf("%d", &i);
for(int ct=0; ct<i; ct++)
{
char buff[28];
scanf("%s", buff); // if I just press enter here
prtinf("%s\n", buff); // then I must get \n\n here
}
Using fgets
to read in a line is simpler and more robust:
if (!fgets(buff, 28, stdin))
{
// reading failed, do appropriate error handling
// we're just exiting here
exit(EXIT_FAILURE);
}
// We have successfully read in a line, or at least the first 27
// characters of the line. Check whether a full line was read,
// if it was, whether the line was empty
size_t l = strlen(buff); // <string.h> must be included
if (buff[l-1] == '\n')
{
// a full line was read, remove trailing newline unless
// the line was empty
if (l > 1)
{
buff[l-1] = 0;
}
}
else
{
// the input was too long, what now?
// leave the remaining input for the next iteration or
// empty the input buffer?
}
printf("%s\n",buff);
It doesn't work with scanf("%s",buff)
because most scanf
conversions ignore leading white space:
Input white-space characters (as specified by the
isspace
function) are skipped, unless the specification includes a[
,c
, orn
specifier.
So if the user inputs an empty line, scanf
ignores that input unless its format is one of the exceptional.
You can use scanf
with a character set format instead,
scanf("%27[^\n]%*c", buff);
to read all characters until a newline (but limited to 28 - 1
here to avoid buffer overruns), and then consume a newline without storing it (the *
in the %*c
conversion specifier suppresses assignment), that would handle non-empty lines consisting entirely of whitespace, which the %s
conversion would not. But if the first character of the input is a newline, the %27[^\n]
conversion fails (thanks to chux for drawing attention to that), the newline is left in the input buffer, and subsequent scans with that format would also fail if the newline isn't removed from the input buffer.
A somewhat robust (but ugly; and not dealing with too long input) loop using scanf
would, as far as I can see, need to check for a newline before scanning, e.g.
for(int ct = 0; ct < i; ++ct)
{
int ch = getchar();
if (ch == EOF)
{
// something bad happened; we quit
exit(EXIT_FAILURE);
}
if (ch == '\n')
{
// we had an empty line
printf("\n\n");
}
else
{
// The first character was not a newline, scanning
// with the character set format would have succeeded.
// But we don't know what comes next, so we put the
// character back first.
// Although one character of pushback is guaranteed,
if (ungetc(ch,stdin) == EOF)
{
// pushback failed
exit(EXIT_FAILURE);
}
scanf("%27[^\n]%*c",buff);
printf("%s\n",buff);
}
}
Use fgets
, really. It's better.
I have two solutions for this:
fgets
instead of scanf
.\n
at the end of the string, because you know the use will end the input with \n
....
char buf[28];
fgets(buf, 28, stdin);
...
#include <string.h>
...
char buf[28];
scanf("%s", buf);
strcat(buf, "\n"); // add the newline to the string
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With