CheetahBongos
CheetahBongos

Reputation: 197

Don't understand function to count digits in character array

I am having a lot of trouble understanding my professor's solution to a program that counts the number of digits in a character array.

int main(void)
{
    char* s[] = {"12, 34, 56, 78",
                 "82.16, 41.296",
                 "2, -3, 5, -7, 11, -13, 17, -19",
                 "9.00009, 90.0009, 900.009, 9000.09, 90000.9"};
    int i, rows = sizeof(s)/sizeof(s[0]);

    for(i = 0; i < rows; i++) {
      digitCounts( s[i] );
  }
}

void digitCounts(char* s) {
    int counts[10] = { 0 };
    int i = 0;

    while( s[i] != '\0' )
    {
        if('0' <= s[i] && s[i] <= '9')
            counts[ s[i] - '0' ]++;

        i++;
    }

    for(i = 0; i < 9; i++)
        printf("%d, ", counts[i]);

    printf("%d\n\n", counts[i]);
}

Can someone please help me understand this section specifically:

while( s[i] != '\0' )
{
    if('0' <= s[i] && s[i] <= '9')
        counts[ s[i] - '0' ]++;

    i++;
}

I understand the while-loop conditional: if the element at s[i] is not equal to NUL, then proceed. But the if statement is confusing to me because are you comparing numerical values or string values? How can a string value be greater than or less than another? e.g. '1' <= '9'. Also, wouldn't the first element of s[] be '12'? Not '1'. In other words, it wouldn't be a single digit.

Please help I am really lost!

Upvotes: 1

Views: 821

Answers (5)

John Bode
John Bode

Reputation: 123448

The line

if('0' <= s[i] && s[i] <= '9')

is comparing individual characters within a single string against the character constants '0' and '9' (ASCII values 48 and 57).

Remember that a string in C is a sequence of character values followed by a 0-valued terminator, and string literals are delimited by double quotes ("). Strings (including string literals) are stored as arrays of char. Each element of s contains the address of the first character of an array of char, sort of like the following1:

   +---+         +---+---+---+
s: |   | ------> |'1'|'2'| 0 |
   +---+         +---+---+---+
   |   | ----+
   +---+     |   +---+---+---+    
   |   | -+  +-> |'3'|'4'| 0 |
   +---+  |      +---+---+---+ 
    ...   |
          |      +---+---+---+
          +----> |'5'|'6'| 0 |
                 +---+---+---+

Thus, s[0] points to the string "12", s[1] points to the string "34", etc. Each s[i] is passed to the digitCounts function, which walks through the string character by character and checks each to see if it is a digit.

The C language definition guarantees that the values of the digit characters '0', '1', '2', etc., are sequential, so any character value between '0' and '9' must be a digit character. So the condition

if ( '0' <= s[i] && s[i] <= '9' )

is checking to see if each s[i] is a digit character (character constants like '0' and '9' are delimited by single quotes). Note that there is a library function that does this same thing, with the bonus that it takes locale into account:

#include <ctype.h>
...
if ( isdigit( s[i] ) ) // does the same thing as the line above.   

Your professor's code is ... not awesome. It would have been nice if he used different names for the array of strings in main (such as numberStringList) vs. the input parameter to digitCounts (such as numberString); I think that accounts for some of your confusion. And he should have shown you how to use the isdigit function instead of hand-hacking the check.


  1. In main, s is declared as an array of pointer to char (char *[]). The size of the array is taken from the number of initializers in the initializer list.

    Each string literal in the initializer is also an array of char, but under most circumstances array expressions are converted ("decay") to pointer expressions, and the value of the expression is the address of the first element of the array. So each s[i] stores the address of the string literal, not the literal itself.

Upvotes: 3

Shahid
Shahid

Reputation: 2330

Here char* s[] means two dimensional array of characters or array of strings. And in digitCounts the argument is char* s which is one dimensional array or a string. That's why, s[0] or the first element of s[] will be '1', not '12'.

Also, '1' <= '9' means ASCII value comparison of character 1 and 9.

Upvotes: 0

DrOliver
DrOliver

Reputation: 26

Those are all char.

With that if statement you understand if the character is a number (the disequalities are actually working on the ASCII values of every char).

Upvotes: 0

ameyCU
ameyCU

Reputation: 16607

while( s[i] != '\0' ){
   if('0' <= s[i] && s[i] <= '9')
      counts[ s[i] - '0' ]++;
   i++;
}

This loop iterates until s[i] is equal to '\0'. Then charcters are compared i.e '0'<=s[i] in this both are characters not string(compared on basis of ASCII values ).

Then if condition is fulfilled count at particular index is incremented in array counts. If charcter at s[i] is '1' then count of index is incresed by one. This 's[i]-'0' , gives the particular integer as '1'-'0' is 1 as difference between their ASCII values.

Upvotes: 0

DanielS
DanielS

Reputation: 774

while( s[i] != '\0' ) //while char at index i is not '\0' (end of string)
{
    if('0' <= s[i] && s[i] <= '9') //if char at index i is between '0' and '9' (a digit)
    counts[ s[i] - '0' ]++; // increase digit count. (counts is an array of       size 10 where each index corresponds to digits 0-9

    i++;
}

Upvotes: 0

Related Questions