rewed
rewed

Reputation: 61

Function of (char)getchar() in C programming

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

Answers (2)

chqrlie
chqrlie

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

Eric Postpischil
Eric Postpischil

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

Related Questions