0

Here I am referring to a question from "codechef.com". Here this below code is used to read the initial count from the user. This will return an integer value.

This is similar to doing a scanf("%d", &n);. But most people are using this type of method to get the information from the user.

I do not understand one line in this code, and I do not understand where the character input gets converted to an integer.

int readuint()
{
int n = 0;
char c = fgetc(stdin);
do {
n = n * 10 + (c - '0');
} while ((c = fgetc(stdin)) != '\n');
return n;
}

The item in question is this line - n = n * 10 + (c - '0'); What is this line doing ??

For full code visit : http://www.codechef.com/viewsolution/1221364

0

1 Answer 1

4

If the input is 123, then on each iteration of the loop, it calculates:

n =  0 * 10 + ('1' - '0');
n =  1 * 10 + ('2' - '0');
n = 12 * 10 + ('3' - '0');
assert(n == 123);

The character codes for the digits are always consecutive, so '1' - '0' is 1, etc.

It converts the digits of a number into a number. Get used to the idiom; you will see it a lot in C code.


The code shown is sloppy in a variety of ways:

int readuint()
{
    int n = 0;
    char c = fgetc(stdin);
    do {
        n = n * 10 + (c - '0');
    } while ((c = fgetc(stdin)) != '\n');
    return n;
}

The name indicates it is reading an unsigned integer (uint), but the type used is a signed int. The type of c should be int because fgetc() (and getc() and getchar()) return an int and not a char. There's no way to indicate that it encountered EOF. There's no protection against overflow. There's no protection against non-digits in the input. Fixing all those requires quite a lot of code, but basic self-protection for the code means it should be more like:

int readint(void)
{
    int n = 0;
    int c;
    while ((c = fgetc(stdin) != EOF && isdigit(c))
        n = n * 10 + (c - '0');
    if (c != EOF && c != '\n')
        ungetc(fp, c);
    return n;
}

There's still no protection against overflow, but it has rudimentary protection against EOF and non-digits in the input (leaving characters other than a newline or EOF to be reprocessed by putting it back for the next read operation).


'1'-'0' (char) = (int)1? How does this conversion happen? From char to int: is it because we are assigning to an integer container — i.e int n?

As Elchonon Edelson said, the character constants such as '0' and '1' are integer constants in C (they'd be char constants in C++), and the values for '0' and '1' are very often 48 and 49 respectively (but the C standard does not guarantee that!). So, 49 - 48 gives 1, of course.

Sign up to request clarification or add additional context in comments.

6 Comments

'1'-'0' (char) = (int)1 ??? how this conversion is happening ?? from char to int. is it because we are assigning to an integer container ? i.e int n ??
The character constants (such as '0') actually have int type in C. Additionally, if you assign a value from a smaller-sized integer to a variable of a larger integer type, the value is promoted automatically. It doesn't require effort to convert a 1 that is of char type or short type to a 1 of int type or long type...
Would not scanf() functionality also ungetc('\n')? BTW: I believe it is OK to ungetc(EOF) C11 7.21.7.10.4 "If the value of c equals that of the macro EOF, the operation fails and the input stream is unchanged." Thus recommend dropping the if (c != EOF && c != '\n').
Further simplification idea: change to while (isdigit(c = fgetc(stdin))). isdigit(EOF) returns 0.
@chux: I thought about that when writing the code and decided I didn't like it and wouldn't write it like that. You're correct; it could be done. However, I don't feel that it is good style, for all it is correct.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.