Reputation: 61
My friend asked me what is (char)getchar()
which he found in some online code and I googled and found 0 results of it being used, I thought the regular usage is just ch = getchar()
. This is the code he found, Can anyone explain what is this function?
else if (input == 2)
{
if (notes_counter != LIST_SIZE)
{
printf("Enter header: ");
getchar();
char c = (char)getchar();
int tmp_count = 0;
while (c != '\n' && tmp_count < HEADER)
{
note[notes_counter].header[tmp_count++] = c;
c = (char)getchar();
}
note[notes_counter].header[tmp_count] = '\0';
printf("Enter content: ");
c = (char)getchar();
tmp_count = 0;
while (c != '\n' && tmp_count < CONTENT)
{
note[notes_counter].content[tmp_count++] = c;
c = (char)getchar();
}
note[notes_counter].content[tmp_count] = '\0';
printf("\n");
notes_counter++;
}
}
Upvotes: 2
Views: 369
Reputation: 144750
The code is a typical example of incorrect usage of the getchar()
function.
getchar()
, and more generally getc(fp)
and fgetc(fp)
return a byte from the stream as a positive value between 0
and UCHAR_MAX
or the special negative value EOF
upon error or end of file.
Storing this value into a variable of type char
loses information. It makes testing for EOF
unreliable if type char
is signed: if EOF
has the value (-1)
it cannot be distinguished from a valid byte value 255
, which most likely gets converted to -1
when stored to a char
variable on CPUs with 8-bit bytes
impossible on architectures where type char
is unsigned by default, on which all char
values are different from EOF
.
In this program, the variables receiving the getchar()
return value should have type int
.
Note also that EOF
is not tested in the code fragment, causing invalid input strings such as long sequences of ÿÿÿÿÿÿÿÿ
at end of file.
Here is a modified version:
else if (input == 2)
{
if (notes_counter != LIST_SIZE)
{
int c;
// consume the rest of the input line left pending by `scanf()`
// this should be performed earlier in the function
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("Enter header: ");
int tmp_count = 0;
while ((c = getchar()) != EOF && c != '\n') {
if (tmp_count + 1 < HEADER)
note[notes_counter].header[tmp_count++] = c;
}
note[notes_counter].header[tmp_count] = '\0';
printf("Enter content: ");
tmp_count = 0;
while ((c = getchar()) != EOF && c != '\n')
if (tmp_count + 1 < CONTENT)
note[notes_counter].content[tmp_count++] = c;
}
note[notes_counter].content[tmp_count] = '\0';
printf("\n");
notes_counter++;
}
}
Upvotes: 3
Reputation: 222724
(char)getchar()
is a mistake. Never use it.
getchar
returns an int
that is either an unsigned char
value of a character that was read or is the value of EOF
, which is negative. If you convert it to char
, you lose the distinction between EOF
and some character that maps to the same char
value.
The result of getchar
should always be assigned to an int
object, not a char
object, so that these values are preserved, and the result should be tested to see if it is EOF
before the program assumes a character has been read. Since the program uses c
to store the result of getchar
, c
should be declared as int c
, not char c
.
It is possible a compiler issued a warning for c = getchar();
because that assignment implicitly converts an int
to a char
, which can lose information as mentioned above. (This warning is not always issued by a compiler; it may depend on warning switches used.) The correct solution for that warning is to change c
to an int
, not to insert a cast to char
.
About the conversion: The C standard allows char
to be either signed or unsigned. If it is unsigned, then (char) getchar()
will convert an EOF
returned by getchar()
to some non-negative value, which will be the same value as one of the character values. If it is signed, then (char) getchar()
will convert some of the unsigned char
character values to char
in an implementation-defined way, and some of those conversions may produce the same value as EOF
.
Upvotes: 5