views:

307

answers:

5

Hello everyone,

I am having trouble with a homework question that I've been working at for quite some time. I don't know exactly why the question is asking and need some clarification on that and also a push in the right direction.

Here is the question:

(2) Solve this problem using one single subscripted array of counters. The program uses an array of characters defined using the C initialization feature. The program counts the number of each of the alphabetic characters a to z (only lower case characters are counted) and prints a report (in a neat table) of the number of occurrences of each lower case character found. Only print the counts for the letters that occur at least once. That is do not print a count if it is zero. DO NOT use a switch statement in your solution. NOTE: if x is of type char, x-‘a’ is the difference between the ASCII codes for the character in x and the character ‘a’. For example if x holds the character ‘c’ then x-‘a’ has the value 2, while if x holds the character ‘d’, then x-‘a’ has the value 3. Provide test results using the following string:

“This is an example of text for exercise (2).”

And here is my source code so far:

#include<stdio.h>

int main() {

    char c[] = "This is an example of text for exercise (2).";
    char d[26];

    int i;
    int j = 0;
    int k;

    j = 0;

    //char s = 97;

    for(i = 0; i < sizeof(c); i++) {
        for(s = 'a'; s < 'z'; s++){
            if( c[i] == s){

                k++;
                printf("%c,%d\n", s, k);
                k = 0;

            }
        }
    }
    return 0;

}

As you can see, my current solution is a little anemic. Thanks for the help, and I know everyone on the net doesn't necessarily like helping with other people's homework. ;P

+2  A: 
char c[] = "This is an example of text for exercise (2).";
int d[26] = {0}, i, value;

for(i=0; i < sizeof(c) - 1; i++){ //-1 to exclude terminating NULL
   value = c[i]-'a';
   if(value < 26 && value >= 0) d[value]++;
}

for(i=0; i < 26; i++){
   if(d[i]) printf("Alphabet-%c Count-%d\n", 'a'+i, d[i]);
}

Corrected. Thanks caf and Leffler.

N 1.1
Thank you, I see how I was trying to over complicate the answer.
Craig
This solution writes outside of the defined bounds of the array `d`.
caf
That has problems - what about the spaces, parentheses, digit, dots (and terminal NUL)?
Jonathan Leffler
It still writes outside of the array - `c[i] - 'a'` might be negative (for example for `'T'` and `' '`).
caf
@caf : updated.
N 1.1
@nvl: you should use `isalpha` or `islower`.
Alok
@Alok: maybe. As long as the program doesn't do 'setlocale("");', using 'islower()' is safe enough - the locale will be the C locale. Using 'isalpha()' is not a good idea; the capital T is to be ignored. You'd then rewrite the loop with `'if (islower(c[i])) d[c[i]-'a']++;`' in the body. You might or might not add an '(unsigned char)' cast to the argument to 'islower()'; it won't hurt with the test data, but with signed char and accented characters in 8859-1 or 8859-15 code sets, it would matter.
Jonathan Leffler
@Jonathan: yeah, I wasn't thinking properly when I wrote the above. As you said, `isalpha()` doesn't really buy one anything, and `islower()` is also of limited use here. Sorry!
Alok
+2  A: 

The intention of the question is for you to figure out how to efficiently convert a character between 'a' and 'z' into an index between 0 and 25. You are apparently allowed to assume ASCII for this (although the C standard does not guarantee any particular character set), which has the useful property that values of the characters 'a' through 'z' are sequential.

Once you've done that, you can increment the corresponding slot in your array d (note that you will need to initialise that array to all-zeroes to begin with, which can be done simply with char d[26] = { 0 };. At the end, you'd scan through the array d and print the counts out that are greater than zero, along with the corresponding character (which will involve the reverse transformation - from an index 0 through 25 into a character 'a' through 'z').

caf
+2  A: 

Fortunately for you, you do not seem to be required to produce a solution that would work on an EBCDIC machine (mainframe).

Your inner loop needs to be replaced by a conditional:

if (c[i] is lower-case alphabetic)
    increment the appropriate count in the d-array

After finishing the string, you then need a loop to scan through the d-array, printing out the letter corresponding to the entry and the count associated with it.

Your d-array uses 'char' for the counts; that is OK for the exercise but you would probably need to use a bigger integer type for a general purpose solution. You should also ensure that it is initialized to all zeros; it is difficult to get meaningful information out of random garbage (and the language does not guarantee that anything other than garbage will be on the stack where the d-array is stored).

Jonathan Leffler
A: 

.

for(s = 'a'; s < 'z'; s++){ 
    j=0;
    for(i = 0; i < sizeof(c); i++) { 
         if( c[i] == s )
            j++;
    }
    if (j > 0)
        printf("%c,%d\n", s, j); 
}
Federico
Are you sure about any of this? Did you try running it?
Jonathan Leffler
I ran it and there are a few missing brackets on the if statement but besides some little syntax errors it is fine.
Craig
Jonathan Leffler
This algorithm scans the string 26 times. For a short string, this is not a problem. If the data had to be read from a file, or if the string was multiple megabytes in size, then it might be a problem compared with the solutions that scan the data just once. But it is an interesting alternative way to look at the problem - for each interesting character (letter), count the number of times it occurs, and print the character and the count if it appears at all.
Jonathan Leffler
A: 
char c[] = "This is an example of text for exercise (2).";
char d[26];
int i;
int j;

for(i = 0; i < 26; i++)
{
    d[i] = 0; // Set the frequency of the letter to zero before we start counting.
    for(j = 0; j < strlen(c); j++)
    {
        if(c[j] == i + 'a')
            d[i]++;
    }
    if(d[i] > 0) // If the frequency of the letter is greater than 0, show it.
        printf("%c - %d\n", (i + 'a'), d[i]);
}
Bob