Hey, guys. I'm working on a program that's supposed to take a phrase that the user inputs, then display the frequency of all letters appearing within that phrase, from most frequent to least frequent. So far, I've managed to get it to display the frequency of the letters in alphabetical order, but I cannot get it to display the results from most to least. Here's what I have so far.

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

const int alphabet = 26;
void sort(int a[], int number);
void sort2(char a[], int number);

int main(){
    char disp, limit = '.';
    char sentence[255];
    int letters = 0, counters[alphabet] = {0};
    cout << "This program will take an input phrase of lowercase letters \n";
    cout << "and count the frequency of every letter that it is composed of.\n";
    cout << "Please type in a sentence composed of all lowercase letters, \n";
    cout << "and include a period at the end: ";
     char next;
     for (int i = 0; next != limit; i++) {
         cin.get(next);
         letters++; 
         sentence[i] = next; }  
         sort(counters, letters);
     for(int i = 0; sentence[i] > 0; i++) {
             counters[sentence[i]-'a']++; }



    cout << endl;                 
    cout << "Letter       Frequency\n" << endl;             
     for (int i = 0; i < alphabet; i++) {
     if (counters[i] > 0) {
        disp = i + 'a';
        cout << disp << setw(13) << counters[i] << endl; }}
        cout << endl;
             
    system("pause");
    return 0;
}

void sort(int a[], int number){
     int temp, i, j;
	 for ( i = 0; i < number; ++i )
   {
      for ( j = i; j < number; ++j )
      {
         if ( a[i] > a[j] )
         {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
         }
      }
   }
}

Anyone have some ideas? Thanks in advance.

Recommended Answers

All 10 Replies

why don't you just use getline() to input the sentence instead of that more complicated use of get().

cin.getline(sentence,sizeof(sentence));
letters = strlen(sentence);

Now you will probably have to use a structure of letter number and frequency so that you can sort the structures by frequency while maintaining the relationship with its letter value

struct frequency
{
    char letter;
    int count;
};
vector<frequency> counters;

At this point you have to iterate through sentence, search counters array for the current letter. If not found then add one to the array otherwise if found just increment the count for that letter.

Here is how to sort a vector

Sounds a lot simpler. Unfortunately, I don't believe that we are allowed to use vectors until the next project. Thank you, however, either way.

In that case, you must pass both arrays to the sort function. When you exchange members of the array upon which you are sorting, also exchange the same members of the other array.

In that case, you must pass both arrays to the sort function. When you exchange members of the array upon which you are sorting, also exchange the same members of the other array.

Do you mean something like the following?:

void sort(int a[], char x[], int number){
     int temp, i, j;
	 for ( i = 0; i < number; ++i )
   {
      for ( j = i; j < number; ++j )
      {
         if ( a[i] > a[j] )
         {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;
            temp = x[i];
            x[i] = x[j];
            x[j] = temp;
         }
      }
   }
}

Yep, something like that.

For clarity's sake, since array x is of type char, I'd create a separate temp variable of type char for it. But that's just me.

Well, I added the new sort code, but unfortunately it doesn't seem to be sorting it correctly. The output comes up with the letter position alphabet pushed forward by the number of total letters input above two (Ex: User inputs 'ddddddd.'. There were 7 letters, so results show as 'Letter: i Frequency: 7', the d having been shifted 5 places forward.) Here's what I have so far.

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

const int alphabet = 26;
void sort(int a[], char x[], int number);


int main(){
    char disp, limit = '.';
    char sentence[255];
    int letters = 0, counters[alphabet] = {0};
    cout << "This program will take an input phrase of lowercase letters \n";
    cout << "and count the frequency of every letter that it is composed of.\n";
    cout << "Please type in a sentence composed of all lowercase letters, \n";
    cout << "and include a period at the end: ";
     char next;
     for (int i = 0; next != limit; i++) {
         cin.get(next);
         letters++; 
         sentence[i] = next;
          }  
             
                    
     for(int i = 0; sentence[i] > 0; i++) {
             counters[sentence[i]-'a']++; }
          
        sort(counters, sentence, letters);
                      
    cout << endl;                 
    cout << "Letter       Frequency\n" << endl;             
     for (int i = 0; i < alphabet; i++) {
     if (counters[i] > 0) {
        disp = i + 'a';
        cout << disp << setw(13) << counters[i] << endl; }}
        cout << endl;
             
    system("pause");
    return 0;
}




void sort(int a[], char x[], int number){
     int temp, i, j;
     char temp2;
	 for ( i = 0; i <= number; ++i )
   {
      for ( j = i; j <= number; ++j )
      {
         if ( a[i] > a[j] )
         {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;

            temp2 = x[i];
            x[i] = x[j];
            x[j] = temp2;}
         }
      }
   }

You've got a major logic problem or two.

As it stands, you use the array element that correspond to a letter's position in the alphabet to count that letter. With that arrangement, you cannot reorder the data to indicate which letters have the higher frequency. When you sort the array with the counts, you're breaking the correspondence of the array index = letter.

You are sending the original input sequence to the sort function, does it make any sense to sort that?

What you probably want is to create a char array, fill it in a loop with values 'a' to 'z', and pass that to the sort along with the number array.

In your sort function, you are going one step to far when you write the loops as:

for ( i = 0; i <= number; ++i )

you want to go to strictly less than 'number', not less than or equal to. In fact, for selection sort, the loops should be

for ( i = 0; i < number-1; ++i )
         for( j = i+1; j < number; j++ )

And, you are sorting in an ascending fashion (which is most common), but your problem, as I understand it, wants the most frequent items listed first. Change the direction of the comparison in the sort.

Alright. Got rid of some code and such based on that advice (Thanks a lot by the way, vmanes. I appreciate it.) I've run across something odd, though, which I'm sure is something I'm overlooking but just can't find it in the coding. It will display input in descending order, but only if the letters being counted come before the letter 'L' (Example: Input is 'deeeeeeee.' and display is correctly ascending, but 'dmmmmm' shows ascending.) Here's what I have now.

#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;

const int alphabet = 26;
void sort(int a[], char x[], int number);
void scan(int a[], char x[], char input);

int main(){
    char limit = '.';
    char alphalower[alphabet] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
    int letters = 0, counters[alphabet] = {0};

    cout << "This program will take an input phrase of lowercase letters \n";
    cout << "and count the frequency of every letter that it is composed of.\n";
    cout << "Please type in a sentence composed of all lowercase letters, \n";
    cout << "and include a period at the end: ";
     char next;
     for (int i = 0; next != limit; i++) {
         cin.get(next);
         letters++; 
         scan(counters, alphalower, next);
         }  
         
     sort(counters, alphalower, letters);  
                                                    
    cout << endl;                 
    cout << "Letter       Frequency\n" << endl;             
     for (int i = 0; i < alphabet; i++) {
     if (counters[i] > 0) {
        cout << alphalower[i] << setw(13) << counters[i] << endl; }}
        cout << endl;
             
    system("pause");
    return 0;
}

          


void sort(int a[], char x[], int number)
     {
     int temp, i, j;
     char temp2;
     for (i = 0; i < (number-1); i++){         
         for(j = (i+1); j < number; j++) {
               if ( a[i] < a[j] )
         {
            temp = a[i];
            a[i] = a[j];
            a[j] = temp;

            temp2 = x[i];
            x[i] = x[j];
            x[j] = temp2;}
         }
      }
   }


void scan(int a[], char x[], char input)
     {
     for (int i = 0; i < alphabet; i++){
         if (input == x[i]) {
                  a[i]++;}
                  }
     }

Look at the following line:

sort(counters, alphalower, letters);

What is the information that variable letters holds?

Is that really the value that should limit how far in the array the sort function looks?

D'oh, you're totally right. There we go, all working with that change. Thanks again for all the help, vmanes. Gonna mark this as solved.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.