I observed some behavior I can't explain myself when using printf to print a character via format-string.
It seems that when the character is newline ('\n'), the printf ignores everything up to (including) '%c' and just prints the remaining part.
Here is a minimal example (user input to disable optimization):
#include <stdio.h>
int main(){
int c;
scanf("%d", &c); //read char by ascii id
printf("FOO%cBAR (id %i)\n", c,c);
return 0;
}
Entering 45 (the code for '-') results in output "FOO-BAR", but entering 13 ('\n') just prints "BAR". This happens both in gcc 6.3.1 and clang 3.9.1, on -Og and -O3 optimisation levels, on an linux.
This should not be related to output buffering if I'm not mistaken.
Is this behavior intended?
That is because character 13 is "carriage return".
After that the first part of the message is over-written.
Newline is character 10.
From this answer :
\r is carriage return and moves the cursor back like if i will do-
printf("stackoverflow\rnine")
ninekoverflow
means it has shifted the cursor to the beginning of "stackoverflow" and overwrites the starting four characters since "nine" is four character long.
In this case,
BAR (id %i)\n
will overwrite "FOO".
Related
wrote this code to "find if the given character is a digit or not"
#include<stdio.h>
int main()
{
char ch;
printf("enter a character");
scanf("%c", &ch);
printf("%c", ch>='0'&&ch<='9');
return 0;
}
this got compiled, but after taking the input it didn't give any output.
However, on changing the %c in the second last line to %d format specifier it indeed worked. I'm a bit confused as in why %d worked but %c didn't though the variable is of character datatype.
Characters in C are really just numbers in a token table. The %c is mainly there to do the translation between the alphanumeric token table that humans like to read/write and the raw binary that the C program uses internally.
The expression ch>='0'&&ch<='9' evaluates to 1 or 0 which is a raw binary integer of type int (it would be type bool in C++). If you attempt to print that one with %c, you'll get the symbol table character with index 0 or 1, which isn't even a printable character (0-31 aren't printable). So you print a non-printable character... either you'll see nothing or you'll see some strange symbols.
Instead you need to use %d for printing an integer, then printf will do the correct conversion to the printable symbols '1' and '0'
As a side-note, make it a habit to always end your (sequence of) printf statements with \n since that "flushes the output buffer" = actually prints to the screen, on many systems. See Why does printf not flush after the call unless a newline is in the format string? for details
In a memory, int take 4 bytes of memory you are trying to storing the int values in a character which will return the ascii value not a int value in %c if you are using a %d which will return the int value which are storing in a memory of 4 bytes memory.
printf("%c %c", getc(stdin), getc(stdin));
rewind(stdin); printf("\n");
printf("%c %c", getchar(), getchar());
output
s
s
s
s
I wrote the source code like that and I pressed s, enter, s, enter sequentially on windows console application using vs2017. Console shows me what I put and print output when I press the key. The result's appearance is like s, enter, enter, space, s, s, enter, enter, space, s. Did I use the function in wrong way?
Q1. I pressed s, enter sequentially, but why output is reversed?
Q2. At output's third line and sixth line, why is there exist whitespace like s not s?.
Explaining the output
The arguments to a function can be evaluated in any order that the compiler chooses.
The original code looked like this (missing printf("\n"); compared to the revised code):
printf("%c %c", getc(stdin), getc(stdin));
rewind(stdin);
printf("%c %c", getchar(), getchar());
Your 'output' in the question is extremely difficult to read and interpret. However, I'm reasonably sure that what you show consists of both your input and the program's output.
You say you type s enter twice. The output you get, copied from the question, is:
s
s
s
s
The first s and the newline that follows are what you typed. The blank line is there because the newline was read by the getc(stdin) that appears first in the argument list, then there's the blank from the format string, and the s which was read by the getc(stdin) that appears second in the argument list. Your compiler, it seems, evaluates the arguments right to left — but you should not rely on that.
Now we run into a problem; there's a newline after the second s that isn't accounted for by the code you showed when I wrote this answer. Since then, you've added the printf("\n"); which explains the output you saw.
Putting that aside, the third s is followed by a newline and is what you typed. And again, the blank line is from the newline and then space and s is the rest of the output, and there's probably a newline after that too.
JFTR, when I run your code (program getc73 compiled from getc73.c), I see:
$ getc73
s
ss
s$
$
The $ is my prompt; the first s is what I type; then the newline, blank and s are printed (with no newline at the end); then the second s on the third line is my next s and return, followed by the newline and blank s. Since there's no newline at the end, my prompt appears immediately after the fourth s. I hit return to print another prompt at the start of the line.
Why rewind(stdin) is a no-op
You can't successfully execute an fseek() call on a terminal device. They don't have any storage so you can't move around like that. The rewind() function is effectively:
void rewind(FILE *fp)
{
fseek(fp, 0, SEEK_SET);
}
So, the rewind(stdin) call fails to rewind, but it has no way to report that to you because it returns no value. It does no good; it doesn't do any harm either. If it had worked, you would not have needed to enter the information twice.
If the standard input had been a file instead of a terminal, then the rewind would succeed — disks are seekable.
Improved formatting
If you were on a POSIX system, I'd suggest you used a feature of POSIX printf() that allows you to print the same argument more than once:
#include <stdio.h>
int main(void)
{
printf("[%1$c] %1$d [%2$c] %2$d\n", getc(stdin), getc(stdin));
printf("[%1$c] %1$d [%2$c] %2$d\n", getchar(), getchar());
return 0;
}
When I run that on my terminal (it's a Mac running macOS Mojave 10.14.6 using GCC 9.2.0), I get:
s
[
] 10 [s] 115
s
[
] 10 [s] 115
The lines with just the s on them are what I typed; the other lines show that the newline is printed before the letter s.
This probably won't work for you in VS2017 — the manual for printf() formats on Windows strongly suggests it won't work. Your best bet, probably, is to use:
#include <stdio.h>
int main(void)
{
printf("%d %d\n", getc(stdin), getc(stdin));
printf("%d %d\n", getchar(), getchar());
return 0;
}
That generates:
s
10 115
s
10 115
Choosing a good format to show what you're seeing is an art form. Don't forget to include newlines at the end of (most) printf() format strings. Obviously, if you're building up a line of output piecemeal, you don't want newlines at the end of intermediate formats, but the majority of printf() statements should have a newline at the end of the format.
scanf not working as expected with a normal input character
So I was just trying out the scanf() and a normal input/output of this function. I know that I had to leave a space before the input character and the operand% so my code is as below. Somehow I don't understand why whatever the input I inserted the output remains 0.
#include<stdio.h>
int main()
{
char c ;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
I was expecting the output will be whatever the character I insert. For example, insert an "A" via keyboard and the output will be exactly an "A".
I'm using a vim environment to edit my code, but I found that if I run this code on codeblocks it works. What's the difference?
It appears you are not providing any non-whitespace (which are eaten away by th space in the format string, including newlines) characters (or perhaps nothing at all) from standard input. If this happens, scanf will fail to parse a char and leaves c uninitialized.
Using uninitialized variable is is Undefined Beheavior, so in theory anything could happen. In practice, from your description, it sounds like memory reserved for c happens to have byte value 0, which is unprintable character, so printf prints something else (maybe /0, maybe nothing). And then the environment (vim) might show you the program exit code, also 0 here (assuming the Undefined Behavior doesn' cause your program to crash).
To fix this, check return value of scanf:
#include<stdio.h>
int main()
{
char c ;
int r = scanf(" %c",&c);
if (r==1) {
// Always print something and add newline
// to be sure we see some output always.
printf("c='%c'\n",c);
} else {
printf("scanf error: %d\n", r);
// If r==-1, errno variable tells what error was
}
return 0;
}
Practical hint: To provide standard input when there is no terminal (so you can't type the input), you can pipe something:
echo A | ./thisprogram
I've tried to run your program (exactly as it appears in your question)
pru.c
#include<stdio.h>
int main()
{
char c ;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
and with the input you posted in your question (just A plus Enter) and got the following result:
$ cc pru.c
$ ./a.out
A
A$ _
which is exactly the expected output. So the problem must be in another place, or you have a completely different scenario and need to provide more information.
I tested this on a PC (Intel Core Duo) with FreeBSD 12.0/CLANG compiler. (here $ is the unix prompt and _ is the cursor after the run) And of course, the program has been edited with vi(1) (this has no impact on the result).
Edit
Try to change
printf("%c",c);
by this
printf("0x%02x, [%c]\n",c,c);
so, you'll get an hex dump of the character just input, and also its representation as printed. The \n at the end is to ensure your shell prompt is not eating (overwriting) the last line output of your program (mostly if you have changed the prompt variable PS1) hidding the printed char.
That should produce (on your posted input) the following output:
$ cc pru.c <--- compilation of new pru.c
$ ./a.out <--- default name for your program executable.
A <--- this is your input (followed by <return>)
0x41, [A] <--- this should be your program output.
$ _ <--- prompt (and cursor) after your program execution
This question already has answers here:
What does space in scanf mean? [duplicate]
(6 answers)
Closed 7 years ago.
The following code gives the bizarre o/p as soon as I compile it.
main() {
char name[3];
float price[3];
int pages[3], i;
printf ( "\nEnter names, prices and no. of pages of 3 books\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
scanf ("%c %f %d", &name[i], &price[i], &pages[i] );
printf ( "\nAnd this is what you entered\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
printf ( "%c %f %d\n", name[i], price[i], pages[i] );
}
But if we give the space in the scanf statement before %c, it gives proper o/p.
Can anyone please explain me why is it so?
Update:-
If I am providing the input like this-
F
123.45
56
J
134
67
K
145
98
then my question is why not we are giving space before %f and space before %d? Why we need to give space before %c only?
Adding the space to the format string enables scanf to consume the newline character from the input that happens everytime you press return. Without the space, name[i] will receive the char '\n', and the real char is left to be misinterpreted by %f.
So, say your input is
a 1.0 2
b 3.0 4
c 5.0 6
The program sees it more like this:
a 1.0 2\nb 3.0 4\nc 5.0 6\n\377
That is, the line-breaks are actual characters in the file (and the \377 here indicates "end of file").
The first scanf will appear to work fine, consuming a char, a float, and an integer. But it leaves the input like this:
\nb 3.0 4\nc 5.0 6\n\377
So the second scanf will read the '\n' as its %c, unless you get rid of it first.
Adding the space to the format string instructs scanf to discard any whitespace characters (any of space ' ', tab '\t', or newline '\n').
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
...
from http://linux.die.net/man/3/scanf
This sort of problem arises whenever you use scanf with %c in a loop. Because, assuming free-form input, newlines can happen anywhere. So, it's common to try to avoid the whole issue by using a two-tiered approach. You read lines of input into a buffer (using fgets); chop-off the silly newline characters; then use sscanf instead of scanf to read from the buffer (string) instead of straight from the file.
Incorrect input using %c
Consider the following snippet of code:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("%c", &y);
printf("%d %c", x, y);
}
Behavior: When you run the above program, the first scanf is called
which will wait for you to enter a decimal number. Say you enter
12(That’s ASCII ‘1’ and ASCII ‘2’). Then you hit the "enter" key to
signal the end of the input. Next the program will execute the second
scanf, except you will notice that the program doesn't wait for you to
input a character and instead goes right ahead to output 12 followed
by a ‘\n’.
Explanation:Why does that happen? Let’s look at the behavior of the
program step-bystep.
Initially there is nothing in the buffer. When the first scanf() is called, it has nothing
to read, and so it waits. It keeps waiting until you type 1,2, then "enter". Now what's in
the buffer are the character 1, the character 2, and the character ‘\n’. Remember that ‘\n’
signifies the end of input, once all fields have been entered, but it is also stored in the
buffer as an ASCII character. At this point scanf will read the largest decimal input from
the buffer and convert that to an integer. In this example, it finds the string "12" and
converts it to the decimal value twelve and puts it in x. Then scanf returns control back to
the main function and returns the value 1, for being able to convert one entry
successfully. In our example, we do not catch the return value of the scanf in a variable.
For robust code, it is important to check the return value of scanf( ) to make sure that the
user inputted the correct data.
What is now left in the buffer is ‘\n’. Next, the second scanf is
called and it's expecting a character. Since the buffer already has
the ‘\n’ character in it, scanf sees that, takes it from the buffer,
and puts it in y. That's why when you execute the printf afterwards,
12 and “enter” are printed to the screen.
Solution: Moral of the story is, enter is a character like any other,
and is inputted to the buffer, and consumed from the buffer by %c just
like any other ASCII character. To fix this, try using this code
instead:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("\n%c", &y); /* note the \n !! */
printf("%d %c", x, y);
}
**
How does this fix the problem?
** So you again type ‘1’,’2’,’\n’. The first scanf reads "1" and "2", converts that to the decimal twelve and leaves the ‘\n’ in the buffer.
The next scanf now expects a ‘\n’ at the beginning of the next input.
It finds the ‘\n’ in the buffer, reads it, and discards it. Now the
buffer is empty and scanf is waiting on the user to input a character.
Say the user inputs ‘c’, followed by the enter key. ‘c’ is now
assigned to y, NOT "enter". Therefore printf will output "12 c" to the
screen. NOTE: there is again a ‘\n’ sitting in the queue now. So if
you need to do another scanf for a single character, you will have to
"consume" that '\n' before taking another character in from the user.
This is not an issue for any other format specifier, as they all ignore white spaces before
the input.
This question already has answers here:
What does space in scanf mean? [duplicate]
(6 answers)
Closed 7 years ago.
The following code gives the bizarre o/p as soon as I compile it.
main() {
char name[3];
float price[3];
int pages[3], i;
printf ( "\nEnter names, prices and no. of pages of 3 books\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
scanf ("%c %f %d", &name[i], &price[i], &pages[i] );
printf ( "\nAnd this is what you entered\n" ) ;
for ( i = 0 ; i <= 2 ; i++ )
printf ( "%c %f %d\n", name[i], price[i], pages[i] );
}
But if we give the space in the scanf statement before %c, it gives proper o/p.
Can anyone please explain me why is it so?
Update:-
If I am providing the input like this-
F
123.45
56
J
134
67
K
145
98
then my question is why not we are giving space before %f and space before %d? Why we need to give space before %c only?
Adding the space to the format string enables scanf to consume the newline character from the input that happens everytime you press return. Without the space, name[i] will receive the char '\n', and the real char is left to be misinterpreted by %f.
So, say your input is
a 1.0 2
b 3.0 4
c 5.0 6
The program sees it more like this:
a 1.0 2\nb 3.0 4\nc 5.0 6\n\377
That is, the line-breaks are actual characters in the file (and the \377 here indicates "end of file").
The first scanf will appear to work fine, consuming a char, a float, and an integer. But it leaves the input like this:
\nb 3.0 4\nc 5.0 6\n\377
So the second scanf will read the '\n' as its %c, unless you get rid of it first.
Adding the space to the format string instructs scanf to discard any whitespace characters (any of space ' ', tab '\t', or newline '\n').
A directive is one of the following:
A sequence of white-space characters (space, tab, newline, etc.; see isspace(3)). This directive matches any amount of white space, including none, in the input.
...
from http://linux.die.net/man/3/scanf
This sort of problem arises whenever you use scanf with %c in a loop. Because, assuming free-form input, newlines can happen anywhere. So, it's common to try to avoid the whole issue by using a two-tiered approach. You read lines of input into a buffer (using fgets); chop-off the silly newline characters; then use sscanf instead of scanf to read from the buffer (string) instead of straight from the file.
Incorrect input using %c
Consider the following snippet of code:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("%c", &y);
printf("%d %c", x, y);
}
Behavior: When you run the above program, the first scanf is called
which will wait for you to enter a decimal number. Say you enter
12(That’s ASCII ‘1’ and ASCII ‘2’). Then you hit the "enter" key to
signal the end of the input. Next the program will execute the second
scanf, except you will notice that the program doesn't wait for you to
input a character and instead goes right ahead to output 12 followed
by a ‘\n’.
Explanation:Why does that happen? Let’s look at the behavior of the
program step-bystep.
Initially there is nothing in the buffer. When the first scanf() is called, it has nothing
to read, and so it waits. It keeps waiting until you type 1,2, then "enter". Now what's in
the buffer are the character 1, the character 2, and the character ‘\n’. Remember that ‘\n’
signifies the end of input, once all fields have been entered, but it is also stored in the
buffer as an ASCII character. At this point scanf will read the largest decimal input from
the buffer and convert that to an integer. In this example, it finds the string "12" and
converts it to the decimal value twelve and puts it in x. Then scanf returns control back to
the main function and returns the value 1, for being able to convert one entry
successfully. In our example, we do not catch the return value of the scanf in a variable.
For robust code, it is important to check the return value of scanf( ) to make sure that the
user inputted the correct data.
What is now left in the buffer is ‘\n’. Next, the second scanf is
called and it's expecting a character. Since the buffer already has
the ‘\n’ character in it, scanf sees that, takes it from the buffer,
and puts it in y. That's why when you execute the printf afterwards,
12 and “enter” are printed to the screen.
Solution: Moral of the story is, enter is a character like any other,
and is inputted to the buffer, and consumed from the buffer by %c just
like any other ASCII character. To fix this, try using this code
instead:
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("\n%c", &y); /* note the \n !! */
printf("%d %c", x, y);
}
**
How does this fix the problem?
** So you again type ‘1’,’2’,’\n’. The first scanf reads "1" and "2", converts that to the decimal twelve and leaves the ‘\n’ in the buffer.
The next scanf now expects a ‘\n’ at the beginning of the next input.
It finds the ‘\n’ in the buffer, reads it, and discards it. Now the
buffer is empty and scanf is waiting on the user to input a character.
Say the user inputs ‘c’, followed by the enter key. ‘c’ is now
assigned to y, NOT "enter". Therefore printf will output "12 c" to the
screen. NOTE: there is again a ‘\n’ sitting in the queue now. So if
you need to do another scanf for a single character, you will have to
"consume" that '\n' before taking another character in from the user.
This is not an issue for any other format specifier, as they all ignore white spaces before
the input.