4

How can I count the number of occurrences in c of each letter (ignoring case) in the string? So that it would print out letter: # number of occurences, I have code to count the occurences of one letter, but how can I count the occurence of each letter in the string?

{
    char
    int count = 0;
    int i;

    //int length = strlen(string);

    for (i = 0; i < 20; i++)
    {
        if (string[i] == ch)
        {
            count++;
        }
    }

    return count;
}

output:

a : 1
b : 0
c : 2
etc...

15 Answers15

8

Let's assume you have a system where char is eight bit and all the characters you're trying to count are encoded using a non-negative number. In this case, you can write:

const char *str = "The quick brown fox jumped over the lazy dog.";

int counts[256] = { 0 };

int i;
size_t len = strlen(str);

for (i = 0; i < len; i++) {
    counts[(int)(str[i])]++;
}

for (i = 0; i < 256; i++) {
    if ( count[i] != 0) {
        printf("The %c. character has %d occurrences.\n", i, counts[i]);
    }
}

Note that this will count all the characters in the string. If you are 100% absolutely positively sure that your string will have only letters (no numbers, no whitespace, no punctuation) inside, then 1. asking for "case insensitiveness" starts to make sense, 2. you can reduce the number of entries to the number of characters in the English alphabet (namely 26) and you can write something like this:

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

const char *str = "TheQuickBrownFoxJumpedOverTheLazyDog";

int counts[26] = { 0 };

int i;
size_t len = strlen(str);

for (i = 0; i < len; i++) {
    // Just in order that we don't shout ourselves in the foot
    char c = str[i];
    if (!isalpha(c)) continue;

    counts[(int)(tolower(c) - 'a')]++;
}

for (i = 0; i < 26; i++) {
    printf("'%c' has %2d occurrences.\n", i + 'a', counts[i]);
}
Woodrow Barlow
  • 8,477
  • 3
  • 48
  • 86
  • This code gives me this: The 0. character has 0 occurrences. The 1. character has 0 occurrences. ..... –  Nov 03 '12 at 21:23
  • @user1786283 what you listed is a **dash** (`-`). I don't believe you got that. –  Nov 03 '12 at 21:23
  • @user1786283 Aaaaaaand... What's wrong with that? It means that the character `0x00` had zero occurrences. And so on. You know, there's a scroll bar in the right side of the terminal window in case you're using a modern GUI-based OS. Also, have you made the effort to try the second code snipped? –  Nov 03 '12 at 21:25
  • size_t len = strlen(str); ^~~~~~~~~~~ Untitled.c:12:1: error: expected identifier or '(' for (i = 0; i < len; i++) { ^ 2 errors generated. –  Nov 03 '12 at 21:31
  • @user1786283 you have to wrap it into an `int main()`. –  Nov 03 '12 at 21:34
  • 1
    The code is incorrect if `char` is signed by default. You should cast `str[i]` as `(unsigned char)str[i]` before using it as an index into `counts` or as an argument to `isalpha()`. Otherwise, negative character values will cause undefined behavior. – chqrlie Oct 13 '18 at 19:06
  • The `(int)` cast is meaningless as it will happen automatically (regardless of whether `char` is signed or unsigned by default) when using a `char` as an index. It might shut up a warning about using a signed char as an index, but doesn't really fix the problem it is warning about -- any negative character value will cause a negative index and undefined behavior. – Chris Dodd Jul 18 '23 at 05:28
  • Also, `tolower(c) - 'a'` will only work if you know the lowercase alphabetic characters are all contiguous. That is the case in most character sets (ASCII and things derived from it), but is not guarenteed by the standard (and is not true EBCDIC) – Chris Dodd Jul 18 '23 at 05:30
2

After Accept Answer

A method that meets these specs: (IMO, the other answers do not meet all)

  1. It is practical/efficient when char has a wide range. Example: CHAR_BIT is 16 or 32, so no use of bool Used[1 << CHAR_BIT];

  2. Works for very long strings (use size_t rather than int).

  3. Does not rely on ASCII. ( Use Upper[] )

  4. Defined behavior when a char < 0. is...() functions are defined for EOF and unsigned char

     static const char Upper[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
     static const char Lower[] = "abcdefghijklmnopqrstuvwxyz";
    
     void LetterOccurrences(size_t *Count, const char *s) {
       memset(Count, 0, sizeof *Count * 26);
       while (*s) {
         unsigned char ch = *s;
         if (isalpha(ch)) {
           const char *caseset = Upper;
           char *p = strchr(caseset, ch);
           if (p == NULL) {
             caseset = Lower;
             p = strchr(caseset, ch);
           }
           if (p != NULL) {
             Count[p - caseset]++;
           }
         }
         s++;
       }
     }
    
     // sample usage
     char *s = foo();
     size_t Count[26];
     LetterOccurrences(Count, s);
     for (int i=0; i<26; i++)
       printf("%c : %zu\n", Upper[i], Count[i]);
     }
    
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
1

Like this:

int counts[26];
memset(counts, 0, sizeof(counts));
char *p = string;
while (*p) {
    counts[tolower(*p++) - 'a']++;
}

This code assumes that the string is null-terminated, and that it contains only characters a through z or A through Z, inclusive.

To understand how this works, recall that after conversion tolower each letter has a code between a and z, and that the codes are consecutive. As the result, tolower(*p) - 'a' evaluates to a number from 0 to 25, inclusive, representing the letter's sequential number in the alphabet.

This code combines ++ and *p to shorten the program.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

One simple possibility would be to make an array of 26 ints, each is a count for a letter a-z:

int alphacount[26] = {0}; //[0] = 'a', [1] = 'b', etc

Then loop through the string and increment the count for each letter:

for(int i = 0; i<strlen(mystring); i++)      //for the whole length of the string
    if(isalpha(mystring[i]))
        alphacount[tolower(mystring[i])-'a']++;  //make the letter lower case (if it's not)
                                                 //then use it as an offset into the array
                                                 //and increment

It's a simple idea that works for A-Z, a-z. If you want to separate by capitals you just need to make the count 52 instead and subtract the correct ASCII offset

Mike
  • 47,263
  • 29
  • 113
  • 177
  • undefined behavior on negative `char` values, inefficient loop test expression, the code assumes that lowercase letters are consecutive in the character set. – chqrlie Oct 13 '18 at 19:24
1
#include <stdio.h>
#include <string.h>
void main()
{
    printf("PLEASE ENTER A STRING\n");
    printf("GIVE ONLY ONE SPACE BETWEEN WORDS\n");
    printf("PRESS ENETR WHEN FINISHED\n");

    char str[100];
    int arr[26]={0};
    char ch;
    int i;

    gets(str);
    int n=strlen(str);

    for(i=0;i<n;i++)
    {
        ch=tolower(str[i]);
        if(ch>=97 && ch<=122)   
        {
            arr[ch-97]++;
        }
    }
    for(i=97;i<=122;i++)
        printf("%c OCCURS %d NUMBER OF TIMES\n",i,arr[i-97]);   
    return 0;
}
Garf365
  • 3,619
  • 5
  • 29
  • 41
mrc_03
  • 21
  • 5
0

You can use the following code.

main()
{
    int i = 0,j=0,count[26]={0};
    char ch = 97;
    char string[100]="Hello how are you buddy ?";
    for (i = 0; i < 100; i++)
    {
        for(j=0;j<26;j++)
            {
            if (tolower(string[i]) == (ch+j))
                {
                    count[j]++;
                }
        }
    }
    for(j=0;j<26;j++)
        {

            printf("\n%c -> %d",97+j,count[j]);

    }

}

Hope this helps.

CCoder
  • 2,305
  • 19
  • 41
  • 1
    For the string `The quick brown fox jumps over the lazy dog.` it gives me, `a -> 0 b -> 1 c -> 1 d -> 0 e -> 1 f -> 1 g -> 0 h -> 1 i -> 1 j -> 0 k -> 1 l -> 0 m -> 0 n -> 1 o -> 2 p -> 0 q -> 1 r -> 1 s -> 0 t -> 1 u -> 1 v -> 0 w -> 1 x -> 1 y -> 0 z -> 0`, but it should be 1 for every letter. –  Nov 03 '12 at 21:13
  • @user1786283 Are you sure you didn't write "jumped"? –  Nov 03 '12 at 21:16
  • Undefined behavior on negative `char` values, inefficient test for lowercase letters, hardcoded ASCII code, broken indentation... – chqrlie Oct 13 '18 at 19:22
0
#include<stdio.h>
#include<string.h>

#define filename "somefile.txt"

int main()
{
    FILE *fp;
    int count[26] = {0}, i, c;  
    char ch;
    char alpha[27] = "abcdefghijklmnopqrstuwxyz";
    fp = fopen(filename,"r");
    if(fp == NULL)
        printf("file not found\n");
    while( (ch = fgetc(fp)) != EOF) {
        c = 0;
        while(alpha[c] != '\0') {

            if(alpha[c] == ch) {
                count[c]++; 
            }
            c++;
        }
    }
    for(i = 0; i<26;i++) {
        printf("character %c occured %d number of times\n",alpha[i], count[i]);
    }
    return 0;
}
Megharaj
  • 1,589
  • 2
  • 20
  • 32
  • Undefined behavior if the file cannot be opened because you do not exit the function. `ch` must be defined as `int` for proper `EOF` detection. – chqrlie Oct 13 '18 at 19:18
0
for (int i=0;i<word.length();i++){
         int counter=0;
         for (int j=0;j<word.length();j++){
             if(word.charAt(i)==word.charAt(j))
             counter++;
             }// inner for
             JOptionPane.showMessageDialog( null,word.charAt(i)+" found "+ counter +" times");
         }// outer for
mero
  • 1
0

Here is the C code with User Defined Function:

/* C Program to count the frequency of characters in a given String */

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

const char letters[] = "abcdefghijklmnopqrstuvwxzy";

void find_frequency(const char *string, int *count);

int main() {
    char string[100];
    int count[26] = { 0 };
    int i;

    printf("Input a string: ");
    if (!fgets(string, sizeof string, stdin))
        return 1;

    find_frequency(string, count);

    printf("Character Counts\n");

    for (i = 0; i < 26; i++) {
        printf("%c\t%d\n", letters[i], count[i]);
    }
    return 0;
}

void find_frequency(const char *string, int *count) {
    int i;
    for (i = 0; string[i] != '\0'; i++) {
        p = strchr(letters, string[i]);
        if (p != NULL) {
            count[p - letters]++;
        }
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Pratik Patil
  • 3,662
  • 3
  • 31
  • 31
  • Undefined behavior if the lowercase letters in the native character are not consecutive, as is the case of EBCDIC. `gets()` is obsolete and dangerous. – chqrlie Oct 13 '18 at 19:16
0
#include<stdio.h>

void frequency_counter(char* str)
{
    int count[256] = {0};  //partial initialization
    int i;

    for(i=0;str[i];i++)
        count[str[i]]++;

    for(i=0;str[i];i++) {
        if(count[str[i]]) {
            printf("%c %d \n",str[i],count[str[i]]);
            count[str[i]]=0;
        }
    }
}

void main()
{
    char str[] = "The quick brown fox jumped over the lazy dog.";
    frequency_counter(str);
}
joce
  • 9,624
  • 19
  • 56
  • 74
0

Have checked that many of the answered are with static array, what if suppose I have special character in the string and want a solution with dynamic concept. There can be many other possible solutions, it is one of them.

here is the solutions with the Linked List.

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

struct Node { 
    char data; 
    int counter;
    struct Node* next; 
};

void printLinkList(struct Node* head)
{
    while (head != NULL) { 
        printf("\n%c occur %d", head->data, head->counter);
        head = head->next;
    }
}

int main(void) {
    char *str = "!count all the occurances of character in string!";
    int i = 0;
    char tempChar;
    struct Node* head = NULL; 
    struct Node* node = NULL; 
    struct Node* first = NULL; 

    for(i = 0; i < strlen(str); i++)
    {
        tempChar = str[i];

        head = first;

        if(head == NULL)
        {
            node = (struct Node*)malloc(sizeof(struct Node));
            node->data = tempChar;
            node->counter = 1;
            node->next = NULL;

            if(first == NULL)
            {
                first = node;
            }
        }
        else
        {
            while (head->next != NULL) { 
                if(head->data == tempChar)
                {
                    head->counter = head->counter + 1;
                    break;
                }
                head = head->next;
            }

            if(head->next == NULL)
            {
                if(head->data == tempChar)
                {
                    head->counter = head->counter + 1;
                }
                else
                {
                    node = (struct Node*)malloc(sizeof(struct Node));
                    node->data = tempChar;
                    node->counter = 1;
                    node->next = NULL;
                    head->next = node;
                }
            }
        }
    }

    printLinkList(first);


    return 0;
}
-1
int charset[256] = {0};
int charcount[256] = {0};

for (i = 0; i < 20; i++)
{
    for(int c = 0; c < 256; c++)
    {
        if(string[i] == charset[c])
        {
           charcount[c]++;
        }
    }
}

charcount will store the occurence of any character in the string.

Jared Burrows
  • 54,294
  • 25
  • 151
  • 185
Gianluca Ghettini
  • 11,129
  • 19
  • 93
  • 159
-1

//This is JavaScript Code.

function countWordOccurences()
{
    // You can use array of words or a sentence split with space.
    var sentence = "The quick brown fox jumped over the lazy dog.";
    //var sentenceArray = ['asdf', 'asdf', 'sfd', 'qwr', 'qwr'];
    var sentenceArray = sentence.split(' ', 1000); 
    var output;
    var temp;
    for(var i = 0; i < sentenceArray.length; i++) {
        var k = 1;
        for(var j = i + 1; j < sentenceArray.length; j++) {
            if(sentenceArray[i] == sentenceArray[j])
                    k = k + 1;
        }
        if(k > 1) {
            i = i + 1;
            output = output + ',' + k + ',' + k;
        }
        else
            output = output + ',' + k;
    }
    alert(sentenceArray + '\n' + output.slice(10).split(',', 500));
}

You can see it live --> http://jsfiddle.net/rammipr/ahq8nxpf/
-1

//c code for count the occurence of each character in a string.

void main()
   {
   int i,j; int c[26],count=0; char a[]="shahid";
   clrscr();
   for(i=0;i<26;i++)
    {
        count=0;
          for(j=0;j<strlen(a);j++)
                {
                 if(a[j]==97+i)
                    {
                     count++;
                         }
                           }
                  c[i]=count;
               }
              for(i=0;i<26;i++)
               {
              j=97+i;
          if(c[i]!=0) {  printf("%c of %d times\n",j,c[i]);
                 }
              }
           getch();
           }
  • So many problems: this solution is extremely inefficient, the code is indented randomly, it uses hardcoded ASCII values, non standard functions, the prototype for `main()` is invalid, the header files are missing – chqrlie Oct 13 '18 at 19:13
-1
protected void btnSave_Click(object sender, EventArgs e)
    {           
        var FullName = "stackoverflow"

        char[] charArray = FullName.ToLower().ToCharArray();
        Dictionary<char, int> counter = new Dictionary<char, int>();
        int tempVar = 0;
        foreach (var item in charArray)
        {
            if (counter.TryGetValue(item, out tempVar))
            {
                counter[item] += 1;
            }
            else
            {
                counter.Add(item, 1);
            }
        }
        //var numberofchars = "";
        foreach (KeyValuePair<char, int> item in counter)
        {
            if (counter.Count > 0)
            {
                //Label1.Text=split(item.
            }
            Response.Write(item.Value + " " + item.Key + "<br />");
            // Label1.Text=item.Value + " " + item.Key + "<br />";
            spnDisplay.InnerText= item.Value + " " + item.Key + "<br />";
        }

    }
YoungHobbit
  • 13,254
  • 9
  • 50
  • 73
Manohar A
  • 27
  • 2