'Count the number of occurrences of each letter in a string

This is my logic. I wrote function for counting the no. of occurrences of each letter in a string. But this doesn't work correctly. Correct me.

void countChar(char *str) {
    int i, j, cnt = 1;
    int l = strlen(str);
    for (i = 0; i < l; i++) {
        for (j = i + 1; j < l; j++) {
            if (str[i] == str[j])
                cnt++;
        }
        printf("\n %c occurs : %d times", str[i], cnt);
        cnt = 1;
    }
}

If I enter Hello then it generates this output:

h occurs : 1 times  
e occurs : 1 times  
l occurs : 2 times  
l occurs : 1 times  
o occurs : 1 times  

Expected output:

h occurs : 1 times  
e occurs : 1 times  
l occurs : 2 times  
o occurs : 1 times


Solution 1:[1]

If I call this as

countChar("aabbccda");

I get various frequencies for each letter:

 a occurs : 3 times
 a occurs : 2 times
 b occurs : 2 times
 b occurs : 1 times
 c occurs : 2 times
 c occurs : 1 times
 d occurs : 1 times
 a occurs : 1 times

There is a clue here: the counts for each letter decrease. Your for loop

for(j=i+1;j<l;j++)

runs from i+1 to the end of the string, so won't look back at previous occurrences of a given letter. If we simply change that line to run from the start of the string again:

for(j=0;j<l;j++)
//    ^------

we get closer:

 a occurs : 4 times
 a occurs : 4 times
 b occurs : 3 times
 b occurs : 3 times
 c occurs : 3 times
 c occurs : 3 times
 d occurs : 2 times
 a occurs : 4 times

However, now we have compared str[i] with str[j] when i==j so get an extra count for each letter.

We can sort that:

void countChar(char *str){
    int i, j, cnt = 1;
    int l = strlen(str);
    for(i=0; i<l; i++){
        for(j=0; j<l; j++){
            if(i!=j && str[i] == str[j]){
            // ^---- extra check
                cnt++;
            }
        }
        printf("\n %c occurs : %d times",str[i],cnt);
        cnt=1;
    }
}

Giving:

a occurs : 3 times
a occurs : 3 times
b occurs : 2 times
b occurs : 2 times
c occurs : 2 times
c occurs : 2 times
d occurs : 1 times
a occurs : 3 times

Now, if we use a std::map instead to store the count for each letter, we can avoid it telling us over and over how many times a letter happens.

In fact, since you labelled this as C++, let's use range based for loops and std::cout too:

void countCharImproved(char *str) {
    std::map<char, int> count;
    int l = strlen(str);
    for(int i=0; i<l; i++) {
        count[str[i]]++;
    }
    for(const auto kvp : count) {
        std::cout << kvp.first << " occurs " << kvp.second << " times\n";
    }
}

Giving the much neater:

a occurs 3 times
b occurs 2 times
c occurs 2 times
d occurs 1 times

Solution 2:[2]

void countChar(char *str){
    int i,j,cnt=1;
    int l;

    for(l=0; str[l]; ++l)//to low case
        str[l] = tolower(str[l]);
    for(i=0;i<l;i++){
        if(!str[i])continue;
        for(j=i+1;j<l;j++){
            if(str[i] == str[j]){
                cnt++;
                str[j] = 0;//Destructive changed so next time not to be the target
            }
        }
        printf("\n %c occurs : %d times",str[i],cnt);
        cnt=1;
    }
}

Solution 3:[3]

In my approach i stored all previously matched charaters in an array and checked for each iteration of the loop if the current character is present in the array

#include<stdio.h>
#include<string.h>
void countChar(char *str){
 char parsed[strlen(str)]; //Array to store previously matched characters
 int flag=0; //Flag to check if currently matching character has occured before
 int i,j,cnt=1,k=0;
 int l=strlen(str);
 for(i=0;i<l;i++){

 //Check if currently matching character has occured before
 for(j=0;j<=k;j++){
if(str[i] == parsed[j]){cnt=1;flag=1;}
 }
 if(flag==1){
   flag=0;
   continue;
 }


 for(j=i+1;j<l;j++){
         if(str[i] == str[j])
             cnt++;
 }
 parsed[k++] = str[i]; //Add currently matched character to array of matched characters
 printf("\n %c occurs : %d times",str[i],cnt);
 cnt=1;
 }
}

void main(){
 countChar("Hello World");
}

Solution 4:[4]

Solution with sorting in pure C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int cmp(const void* a, const void* b)
{
    return ((*(const char*)a) - (*(const char*)b));
}

void countChar(const char *str)
{
    size_t i;
    int count = 1;
    char *sorted = strdup(str);
    size_t len = strlen(sorted);
    qsort(sorted, len, sizeof(char), cmp);

    for (i = 0; i < len; i++, count++)
    {
        if (sorted[i] != sorted[i + 1])
        {
            printf("%c occurs : %d times\n", sorted[i], count);
            count = 0;
        }
    }

    free(sorted);
}

Solution 5:[5]

The simple way...

void countChar(char *str) {
  int arr[256],i;
  for(i=0;i<256;i++) arr[i]=0;
  for(; *str; str++) arr[*str]++;  // or  for(;*str;str++) arr[tolower(*str)]++;

  for(i=32; i<256; i++)
    printf("\n %c occurs : %d times",i, arr[i]);
}

Solution 6:[6]

To find the ouccerrence count of each letter in a string.

public class StringCount {
    public static void main(String[]args) {
        String s = "Mechanical Engineering";
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (s.indexOf(ch) < i) continue;
            int count = 1;
            for (int j = i+1; j < s.length(); j++) {
                if (s.charAt(j) == ch) count++;            
            }
            System.out.println("count of " + ch + " is : " + count);   
        }
    }
}

output :

count of M is : 1
count of e is : 3
count of c is : 2
count of h is : 1
count of a is : 2
count of n is : 4
count of i is : 3
count of l is : 1
count of   is : 1
count of E is : 1
count of g is : 2
count of r is : 1

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 chqrlie
Solution 2
Solution 3 Community
Solution 4 Aleksey
Solution 5 Holger
Solution 6