Question

I'm currently reading 'The C Programming Language' by Kernighan & Richie and I'm struggling to work out what a line does. I think I'm just being a little stupid, and not quite understanding their explanation.

++ndigit[c-'0'];

I've had to change the program ever so slightly as ndigit was previously giving me garbage values, so I just instantiate the array to 0, instead of traversing it with a for loop, and changing the values that way.

#include <stdio.h>

main()
{
    int c, i, nwhite, nother;
    int ndigit[10]= {0};

    nwhite = nother = 0;

    while ((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];
        else if (c == ' ' || c == '\n' || c == '\t')
            ++nwhite;
        else
            ++nother;

    printf("digits =");
    for (i = 0; i < 10; i++) 
        printf (" %d", ndigit[i]);
    printf (", white space = %d, other = %d\n", nwhite, nother);
}  

Using the program as its input, we get this printed to the console -

digits = 7 2 0 0 0 0 0 0 0 1, white space = 104, other = 291

I understand that 7 2 0 0 0 0 0 0 0 1 is a count of how many times the single numbers appear in the input 0 appears 7 times, 1 appears twice etc.)

But, how does the ...[c-'0']; 'work'?

Was it helpful?

Solution

You asked how the below expression works

 c-'0'

The ASCII code of the entered charecter is subtracted from the ASCII code of 0 and it defines the position in the array where the count has to be stored .

Suppose you enter 1 from the keyboard ASCII code for 1 is 49 and ASCII code for 0 is 48. hence

   49-48 =1 

and the count will be stored in the array index location 1 .

OTHER TIPS

In C, when you have a variable c of type char, it actually stores some integer encoding of the char (usually the ASCII code). So c-'0' means the difference of the code of the character contained in c and the character 0. Since the digits are in natural order it convert the digit in the associated number.

c-'0' is technique to give int value == to char number e.g. 1 for '1' , 5 for '5'.

char symbols '0', '1', '2' ..... '9' are assigned continue encoding values so difference of a numeric char constant with '0' gives decimal number. (in your compiler for example in ASCII char they are assigned continues acsii values).

So for example in variable c is '7', then c - '0' == 7;

In your code array declared as:

int ndigit[10]= {0};   
                // default initialized with `0`

So index can be from 0 to 9. So in you code:

++ndigit[c-'0'];  // ndigit[c-'0'] = ndigit[c-'0'] + 1;

increments frequency of a number by 1 when at corresponding digit of a number char.

Ascii is an encoding which gives consecutive id's to consecutive digits. As Eric Postpischil pointed out, the standard demands that property, even though the underlying encoding need not be ascii. Ascii is quite common though.

char c1 = '0';
char c2 = '1';

So whatever number '0' is mapped to, '1' will be that number + 1. In essence:

c2 == c1 + 1

Subtracting '0' from a character which is a digit, will return its numeric value:

'1' - '0' == 1

The C standard requires that the characters '0' to '9' have consecutive values.

'0' represents the value zero as a character and c is the value you enter it calculates to be like this :

'1' - '0' == 1

'2' - '0' == 2

and so on ... i.e equal to the value of c if c is a digit

((c = getchar()) != EOF)
        if (c >= '0' && c <= '9')
            ++ndigit[c-'0'];

c gives you the current character. With the range checking you confirm it is a number by using its ASCII value Check chr column for 0, it says 48 and for 8 it says 56.So, '8'- '0' gives 56 - 48 = 8

ndigit is used to keep track of how many times a number occurs in with each element of the array representing the number of times its subscript has occured. ndigit[0] will ggive you number of times 0 has occurred and so on.. ndigit[x] gives number of times x appeared

[c - '0']

suppose your c i.e current character is 8 then '8' - '0' will give you 8. so you get ndigit[8] and you ++ that value [you initialised it to 0 at start]

Loog at ASCII wikipedia.

The American Standard Code for Information Interchange (ASCII /ˈæski/ ass-kee)1 is a character-encoding scheme originally based on the English alphabet that encodes 128 specified characters - the numbers 0-9, the letters a-z and A-Z, some basic punctuation symbols, some control codes that originated with Teletype machines, and a blank space - into the 7-bit binary integers.

So In the ASCII Scheme the '0' char is the number 48, the char '1' is 41, and so on. So c - '0' is equivalent to c - 48. If c is '1' the expression became 49 - 48 = 1. So in few word 'c' - '0' convert a digit char ['0'-'9'] into an integer [0-9].

Edit 1 As suggested by @Eric Postpischil, ASCII is not part of ANSi C (nor c++). But is very common and all compiler I know use ASCII set.

'0' is a char and it has value 48. You can look up any ASCII table in the google. It works this way because you read from the input char value not the int, so if you don't add "-'0'" part it will increment 48th cell of an array. Instead of "-'0'" you can put "-48", in my opinion it's more readable this way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top