Word and Letter Frequency

Hello all,

I'm very aware that people don't just give out code, but I've been stuck on this for a good 4 hours now. If anyone could look at my code and tell me what's wrong, or provide a quick fix, that would be awesome.

What the program should do:
Menu appears, if the user enters '1'
They enter a sentence ("hello, my friend") and hit enter.
All 26 alphabet letters appear with the number of times that letter has appeared in the text.
The user is then prompted if they wish to repeat, if yes, it does so, if no, it returns to the menu.
If the user enters '2'
They enter a sentence ("hello, my very good friend") and hit enter.
The length of the word (up to 20) appears with the number of that length words that have shown up in the text.
(example: length: 4, frequency: 2)
If they wish to repeat, hit yes, if not, return to menu.
If the user enters '3', the program quits.

Here's what I have:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>

using namespace std;

const int SIZE = 256;
char buffer[SIZE];
const char *delimiters =" \n.?!";
char *tokenPtr;
const int letterSIZE = 26;
int letterCount[letterSIZE] = {0};
int input, i;
char c, answer;

void letterDisplay (char string[]) {

	cout << " Please enter a sentence: ";
	cin.getline(buffer, SIZE);

	for ( i = 0; i < strlen(string); i++) {

	if ('a' <= string[i] && string[i] <= 'z')
	{
		 letterCount[ string[i] - 'a' ]++;
	}
}
	cout << "Letter" << " " << "Frequency" << endl;

	for (char c = 'a'; c <= 'a' + letterSIZE - 1; c++) {

		cout << c << setw(15) << letterCount[c - 'a'] << endl;
	}


}


void wordCount (char words[]) {

		cout << " Please enter a sentence: ";
		cin.getline(buffer, SIZE);

		tokenPtr = strtok(buffer, delimiters);
		int length = strlen(tokenPtr);

		int frequency[ 21 ] = { 0 };
		int count = 0;


		for ( int i = 0; i < strlen(words); i++ )
		     frequency[ length ]++;
		     count++;

		cout << "Length" << setw( 17 ) << "Frequency" << endl;

		for ( int j = 1; j < 21; j++ )
		   cout << setw( 6 ) << j << setw( 17 ) << frequency[j]
           << endl;

}

void menuDisplay () {
	cout << "1." << " " << "Letter level" << endl;
	cout << "2." << " " << "Word level" << endl;
	cout << "3." << " " << "Quit" << endl;

}





int main () {

	menuDisplay();
	cin >> input;

	if (input == 1) {
		letterDisplay(buffer);
		cout << "Do you wish to enter another sentence? (y/n): " << endl;
		cin >> answer;
		if (answer == y) {
			letterDisplay(buffer);
		} else {
			menuDisplay();
		}
	} else if (input == 2) {
		wordCount(buffer);
		cout << "Do you wish to enter another sentence? (y/n): " << endl;
		cin >> answer;
		if (answer == y) {
			wordCount(buffer);
		} else {
			menuDisplay();
		}
	} else if (input == 3) {
		break;
	}




	return 0;

}

Last edited on
Hi,

Just a few changes that you need to make

1
2
3
        menuDisplay();
	cin >> input;
	cin.ignore(1);


The Cin.ignore is added so that you dispose of the end of line character thats sitting
in the buffer.

1
2
3
    if (answer == y)
    //should be replaced by. Two occurances
    if (answer == 'y')


and

1
2
3
else if (input == 3) {
		return(0);
}


change the break in your code to a return. {break only breaks from loop commands}

also Your program probably needs to check for capital letters.

The only other thing tat I would suggest is that you put the 'another sentence (y/n)'
into a while loop as you can only input two sentences the way it is.

Hope this was helpful
Shredded

Thank you for your help, that saved me from a couple of errors I was having.

My wordCount function still isn't doing what I want though...

Let's say the user inputs 2 at the menu and enters "i have many of them". What needs to be displayed is this:

Length (indicating number of chars a word contains)
1
2
3
4

Frequency (indicating number of times that length has appeared in sentence)
1
1
0
3

Right now it finds only the first word and although it identifies the correct length, the frequency is displayed as the same number as the length.

Can somebody check that method to fix this error? I've tried messing around with different variables in the final cout but it just won't work.

Thanks.
Last edited on
cin>> input will break on a space.
Use something like:
1
2
string input = "";
std::getline(cin, input);
;

Then, to work out how many times each letter is present. Use a map that stores a count of them each.
1
2
3
4
map<char, int> letterCount;
for (char letter = 'a'; letter <= 'z'; letter++) {
 letterCount[letter] = 0;
}


With the input now in a string and a map ready to store the results we can iterate through each letter in the input string and count it.
1
2
3
4
5
6
for (unsigned i = 0; i < input.length(); ++i) {
 if (input[i] == ' ')
  continue;

 letterCount[input[i]]++;
}
Thank you Zaita, but I already have my letterCount working the way I need to. It's my wordCount that's faulty. Using my example above, if a user enters "I have many of them", I need my word count to display that there was 1 one-lettered word, 1 two-lettered word, 0 three letter words, and 3 four-lettered words.

Here's my current fuction:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void wordCount (char words[]) {

		cout << " Please enter a sentence: ";
		cin.getline(buffer, SIZE);

		tokenPtr = strtok(buffer, delimiters);
		int length = strlen(tokenPtr);

		int frequency[ 21 ] = { 0 };
		int count = 0;


		for ( int i = 0; i < strlen(words); i++ )
		     frequency[ length ]++;
		     count++;

		cout << "Length" << setw( 17 ) << "Frequency" << endl;

		for ( int j = 1; j < 21; j++ )
		   cout << setw( 6 ) << j << setw( 17 ) << frequency[j]
           << endl;

}


Like I said, this currently only reads the first word typed in, and the frequency count is incorrect. I've been trying to fix this, but to no avail.
Last edited on
Hi again

I think this is like what you need for word count

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
void wordCount (char words[]) {

		cout << " Please enter a sentence: ";
		cin.getline(buffer, SIZE);

		int frequency[ 21 ] = { 0 };
		int count = 0;
		int	pos = 0;
		int	maxLen = 0;

		tokenPtr = strtok(&buffer[pos], delimiters);

		while (tokenPtr != NULL) 
		{
			int length = strlen(tokenPtr);

			pos += length+1;

		        frequency[ length ]++;
		        count++;

			tokenPtr = strtok(&buffer[pos], delimiters);
		}

		cout << "Length" << setw( 17 ) << "Frequency" << endl;

		for ( int j = 1; j <21; j++ )
		   cout << setw( 6 ) << j << setw( 17 ) << frequency[j] << endl;

}


hope I was Helpful
Shredded
Thank you so much Shredded. That was just what I needed - it seems my original loop needed work. Thanks again.
Topic archived. No new replies allowed.