'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 |