Reputation: 40
So I have no idea why this behavior is observed:
#include <stdio.h>
int main()
{
unsigned char c;
char d;
scanf("%hhu", &d);
printf("%c\n", d);
return 0;
}
If I remember correctly %hhu
is for unsigned char
. If I input almost any character like a
, or b
the answer is nothing and d
gets the value 0
. But if I input 97
then d
prints the value a
(so ASCII is converted to char). This clearly not the case when the data type is char
. I can just input the character directly and it is stored.
Also in the slight modification of this code
#include <stdio.h>
int main()
{
unsigned char c;
char d;
int g;
scanf("%hhu", &d);
printf("%c\n", d);
scanf("%d", &g);
printf("%d is g\n", g);
return 0;
}
If I give first input as a character like w
or a
then it just skips the second scanf
, but if the input is a number then it works normally.
Upvotes: 0
Views: 740
Reputation: 385546
a
is not a valid input for %hhu
. An integer (in the Math sense) is expected. If we add error checking (code below), we get:
$ gcc -Wall -Wextra -pedantic a.c -o a && ./a
a
Number of assigned variables: 0
Can't read: Invalid input
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned char c;
int rv = scanf("%hhu", &c);
if (rv == EOF) {
if (ferror(stdin)) {
perror("Can't read");
} else {
fprintf(stderr, "Can't read: Premature EOF\n");
}
exit(1);
}
printf("Number of assigned variables: %d\n", rv);
if (rv < 1) {
fprintf(stderr, "Can't read: Invalid input\n");
exit(1);
}
printf("%hhu\n", c);
return 0;
}
Invalid input stays in the handle's buffer to be obtained by future reads. So an error in a early scanf
can cause later scanf
to fail.
If you wish to proceed after an error, you could simply read until you get a LF to clear any "junk" in the buffer.
void read_stdin_to_eol(void) {
while (1) {
int ch = getchar();
if (ch == '\n' || ch == EOF)
return ch;
}
}
Upvotes: 2
Reputation: 153338
If I remember correctly
%hhu
is forunsigned char
. If I input almost any character like 'a', or 'b' the answer is nothing and d gets the value 0.
"%hhu"
expects input text to be numeric like "123"
. Then the value of 123 is save in d
. d
did not get the value of 0. d
was not changed by the scanf("%hhu", &d);
as input was invalid.
If you want to read a character into an unsigned char
unsigned char d;
if (scanf("%c", &d) == 1) Success();
If you want to read a numeric text into an unsigned char
unsigned char d;
if (scanf("%hhu", &d) == 1) Success();
In all cases, test the return value of scanf()
.
If I give first input as a character like 'w' or 'a' then it just skips the second scanf, but if the input is a number then it works normally.
When scanf()
fails to convert input text per the provided specifiers, scanning stops and the offending text remains in stdin
.
A common code idiom is to read remaining input and toss it until '\n'
.
int ch;
while ((ch = getchar()) != '\n') && ch !- EOF) {
;
}
Upvotes: 2
Reputation: 26066
If I input almost any character like 'a', or 'b' the answer is nothing and d gets the value 0. But if I input 97 then d prints the value a. (so ASCII is converted to char) This clearly not the case when the data type is char.
What scanf
does is not related to the type but to the format specifier you use (which in turn defines what types are expected in the arguments).
When you use %hhu
, the input is read as a signed decimal integer, parsed as strtoul
would, and stored in an unsigned char
. This is why 97
is read correctly.
Further, in both examples you should take into account the return value to know whether there was any failure. That way you will be able to detect errors and do whatever is required, like asking the user again.
Upvotes: 3
Reputation: 51815
You are correct that the %hhu
format specifier expects an unsigned char*
argument. However, the u
part of the format dictates that the input be interpreted as a decimal integer. To input the data as an (unprocessed) character, you should use the %c
format specifier.
Upvotes: 5
Reputation: 75062
Format specifier %u
is for reading decimal integer and %hhu
is %u
with length modifier added.
To read one character to char
variable, use specifier %c
.
Upvotes: 3