0

I'm working on a program that can measure the frequency of letters that appear in a string given by the user. What makes this program a little different is that the frequency I'm trying to obtain for each letter is the evaluation of the amount of times a character appears divided by the total length of the string itself. I'm nearly done with the program but I keep getting all zeroes for all the letters of the alphabet no matter what I do. How can I fix this? This is my program:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAXCHAR 1000
int main()
{
  int c = 0, count[26] = {0}, x, length = 0;
  double frequency;
  char str[MAXCHAR];

  printf("Enter a string\n");
  gets(str);


   while (str[length] != '\0')
      length++;    

   while (str[c] != '\0') 
   {
   /** Considering characters from 'a' to 'z' only and ignoring others. */

      if (str[c] >= 'a' && str[c] <= 'z') 
      {
         x = str[c] - 'a';
         count[x]++;
      }

      c++;
   }
   printf("%d \n" , length);
   frequency = (count[c]/length);
for (c = 0; c < 26; c++)
   printf("%c %lf \n", c + 'a', frequency);
   return 0;
}
JD1997
  • 65
  • 8
  • I guess you may want to convert the int values to double/float before division because of this https://stackoverflow.com/questions/3602827/what-is-the-behavior-of-integer-division – petrch Nov 27 '18 at 23:05

1 Answers1

2

Move the frequency calculation into the loop and cast count[c] or length from int to double to avoid truncating the decimal:

for (c = 0; c < 26; c++) {
    frequency = (double)count[c] / length;
    printf("%c %lf \n", c + 'a', frequency);
}

Output (where str = "stack overflow"):

a 0.071429 
b 0.000000 
c 0.071429 
d 0.000000 
e 0.071429 
f 0.071429 
g 0.000000 
h 0.000000 
i 0.000000 
j 0.000000 
k 0.071429 
l 0.071429 
m 0.000000 
n 0.000000 
o 0.142857 
p 0.000000 
q 0.000000 
r 0.071429 
s 0.071429 
t 0.071429 
u 0.000000 
v 0.071429 
w 0.071429 
x 0.000000 
y 0.000000 
z 0.000000 

Try it!

Note that your length doesn't include the null-terminating buffer which may lead to logical bugs down the road.

Also, from the man pages:

Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • 1
    I didn't notice the data type, but some floating point should work--I don't really see the point of the intermediate variable. Changed to `double`. – ggorlen Nov 27 '18 at 23:20
  • 1
    Note: A trick to avoid the cast (and should it be `float` or `double`) is to assign first to match the destination type - and then divide: `frequency = count[c]; frequency /= length;` – chux - Reinstate Monica Nov 27 '18 at 23:24
  • I see! Thank you so much! – JD1997 Nov 28 '18 at 01:59