Reputation: 454
I am currently reading this book: The C Programming Language - By Kernighan and Ritchie (second Edition) and one of the examples I am having trouble understanding how to check whether the input is digit or not. The example is on Page 22, explaining under the array chapter.
Below is the example.
#include <stdio.h>
/* count digits, white space, others */
main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
{
ndigit[i] = 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);
}
For this example, what confused me is that the author mentioned that the line ++ndigit[c-'0']
checks whether the input character in c is a digit or not. However, I believe that only the if statement ( if (c>= '0' && c<= '9') )
is necessary, and it will check if c is digit or not. Plus, I do not understand why [c-'0']
will check the input(c) is digit or not while the input variable (c) is subtracted from the string-casting ('0').
Any suggestions/explanations would be really appreciated.
Thanks in advance :)
Upvotes: 2
Views: 1674
Reputation: 695
I would try to explain with an example
suppose the input is abc12323
So the frequency of 1=1
frequency of 2=2
frequency of 3=2
if (c >= '0' && c <= '9') //checks whether c is a digit
++ndigit[c-'0'];
Now if you do printf("%d",c) then you will get the ascii value of the
character
for c='0' the ascii value will be 48,c='1' ascii value will be 49 and it goes
till 57 for c='9'.
In your program you are keeping a frequency of the digits in the input so you need to update the index of the digit in the array every time you get it
if you do ndigit[c]++ then it will update ndigit[48] for c='0',ndigit[49] for c='1'
So either you can do ndigit[c-'0']++ as ascii value of '0'=48 in decimal
or you can simply do ndigit[c-48]++ so for c='0' ndigit[0] is updated,c=1'
ndigit[1] is updated
you can check the re factored code here http://ideone.com/nWZxL1
Hope it helps you,Happy Coding
Upvotes: 0
Reputation: 34829
The if
statement checks whether the character is a digit, and the ++ndigit[c-'0']
statement updates the count for that digit. When c
is a character between '0'
and '9'
, then c-'0'
is a number between 0
and 9
. To put it another way, the ASCII value for '0'
is 48 decimal, '1'
is 49, '2'
is 50, etc. So c-'0'
is the same as c-48
, and converts 48,49,50,...
to 0,1,2...
One way to improve your understanding is to add a printf
to the code, e.g. replace
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
with
if (c >= '0' && c <= '9')
{
++ndigit[c-'0'];
printf( "is digit '%c' ASCII=%d array_index=%d\n", c, c, c-'0' );
}
Upvotes: 3