I have a program that is designed to read in a line of text and ouptut the number of words in the line and the number of occurrences of each letter. A word is defined as any string of letters that is delimted at each end by either whitespace, a period, a comma or the beginning of a new line. This is what I have so far. It seems like it continues looping because when I interrupt it, it has these large number counts for the word and letters.

#include <iostream>
#include <cctype>

using namespace std;

void readAndCount (int &numWords, int letterCount[]);
// Reads a line of input. Counts the words and the number
// of occurrences of each letter.

void outputLetterCounts (int letterCount[]);
// Prints the number of occurrences of each letter that
// appears in the input line.


// =========================
//      main function
// =========================
int main()
{
  int numWords;
  int letterCount[26];  // stores the frequency of each letter

  cout << endl;
  cout << "Enter a line of text.." << endl << endl;

  readAndCount (numWords, letterCount);

  cout << endl;
  cout << numWords << " words" << endl;
  outputLetterCounts(letterCount);
 
  return 0;
}

// =========================
//   Function Definitions
// =========================


void readAndCount (int &numWords, int letterCount[])
{
	char name [20];
	int p = 0;
	int occ = 0;
	while (p < 20)
	{
			if (name[p] == '\0') 
			{ 
      				occ = occ+1; 		
			}

		cin >> name[p];
		p = p + 1;	
	}
}		


void outputLetterCounts(int letterCount[])
{
  for (int i = 0; i < 26; i++)
    {
      if (letterCount[i] > 0)
	{
	  cout << letterCount[i] << " " << char('a' + i) << endl;
	}
    }
}

>int occ = 0;
What is occ supposed to do?

>if (name[p] == '\0')
name wasn't initialized, so this is undefined.

There's no need for the array, just take characters as you get them:

void readAndCount (int &numWords, int letterCount[])
{
  char c;

  do {
    if ( !cin.get ( c ) ) 
      break;

    ++letterCount[c - 'a']; // Assuming ASCII and only lower case letters
    
    if ( c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '.' )
      ++numWords;
  } while ( c != '\n' );
}

A couple of things. It has to count Capital letters and lower case letters as the same. I definitely understand now what you mean with the corrections. But my output has these huges numbers. If I put in text "now what" it gives me huge numbers with letters that's not even in the two words.

>It has to count Capital letters and lower case letters as the same.
In that case you'll want to convert to either upper or lower case before doing the test. And you have to be very careful if you use the direct value as an index into the frequency array because any mistakes will overflow the array.

>But my output has these huges numbers.
Remember what I said about initializing your arrays?

int letterCount[26] = {0};

By putting the initializer in at the beginning = {0}, it still outputs high numbers and it doesn't give me the number of letters anymore. I can work with the capital letters if I can just get it to output the correct number of words and characters.

#include <iostream>
#include <cctype>

using namespace std;

void readAndCount (int &numWords, int letterCount[]);
// Reads a line of input. Counts the words and the number
// of occurrences of each letter.

void outputLetterCounts (int letterCount[]);
// Prints the number of occurrences of each letter that
// appears in the input line.


// =========================
//      main function
// =========================
int main()
{
  int numWords;
  int letterCount[26] = {0};  // stores the frequency of each letter

  cout << endl;
  cout << "Enter a line of text.." << endl << endl;

  readAndCount (numWords, letterCount);

  cout << endl;
  cout << numWords << " words" << endl;
  outputLetterCounts(letterCount);
 
  return 0;
}

// =========================
//   Function Definitions
// =========================


void readAndCount (int &numWords, int letterCount[])
{
  	char c;

  	do 
	{
  	  	if ( !cin.get ( c ) ) 
 	  	 ++letterCount[c - 'a'] || ++letterCount[c - 'A']; 

  			  if ( c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '.' )
   			   numWords++;
	} while ( c != '\n' );
}

void outputLetterCounts(int letterCount[])
{
  for (int i = 0; i < 26; i++)
    {
      if (letterCount[i] > 0)
	{
	  cout << letterCount[i] << " " << char('a' + i) << endl;
	}
    }
}

Um...you broke the code that I gave you. That's why it doesn't work. Try this:

void readAndCount (int &numWords, int letterCount[])
{
  char c;

  do 
  {
    // If the character can't be read for some reason
    if ( !cin.get ( c ) ) 
      break;
    
    // Assuming ASCII, and isupper and tolower can't be used
    // Convert if upper case letter to lower case
    if ( c >= 'A' && c <= 'Z' )
      c -= 'A' - 'a';

    // Only works with lower case letters
    ++letterCount[c - 'a']; 

    if ( c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '.' )
      numWords++;
  } while ( c != '\n' );
}

By the way, learn to use code tags and then don't fail to use them whenever posting code.

It counts the letters just fine. As far as the word goes.....it gives a huge number again.

you can type the input text in a text file and write a c code to open the file and count the number of blanks in between the words. the total number of words=number of blanks+1. hope this was helpful

I am typing input from the keyboard. I thought by doing a counter:

if ( c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '.' )
numWords++;

this is counting everytime I run across any of these 4?

Why not printf numWords when you hit enter on the keyboard, and see if it's correct?

It looks like it should be correct, but testing that line of code is very simple.

Yes. So, IF you type in two sentences, the first of which ends in a period and is followed by two spaces before the next sentence begins, you will increment numWords by 3 rather than by 1, which will cause a discrepancy in numWords. If your input can include this multi-sentence syntax (or multiple consective tabs, or other legal punctuation of that sort), this can be taken into account, but you need to understand how the current process works before attempting to figure out how to accomodate those possibilities.

Lerner raises an excellent point. To identify words without the potential for error, you might want to use

int isalnum(char)

to keep tabs on the last character entered before the current character, so you can keep track of words but not be fooled by two spaces in a row.

I am working with strings and vectors. I am unfamiliar with the things you said use.
I am aware of the counter but still unaware of why it is counting this way. My test text is "who is it". I still get a word count that is over 4 million.

Lemme make a little change to Narue's code. This should help with some of the problems you could face, but maybe not with your four million. That one sounds like you're not dealing with the buffer correctly, so at the end of your test statement, it just keeps tallying in the loop unless you hit enter...

void readAndCount (int &numWords, int letterCount[])
{
  char c;
  int lastChar=0; //Keeps track of previous entry. 1 if Alphanumeric, 0 if not. (2 if by sea)

  do 
  {
    // If the character can't be read for some reason
    if ( !cin.get ( c ) ) 
      break;
    
    // Assuming ASCII, and isupper and tolower can't be used
    // Convert if upper case letter to lower case
    if ( c >= 'A' && c <= 'Z' )
      c -= 'A' - 'a';

    // Only works with lower case letters
    ++letterCount[c - 'a']; 

    if (lastChar&&( c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '.' )) /*Doesn't 
false count words this way; Also, due to initialization, will not count spaces, commas, etc. in stream before text entry as words.*/
      numWords++;

    lastChar=isalnum(c); //Set lastChar for next round.
  } while ( c != '\n' );
}

That should help limit massive overcounting. Give it a whirl. If it complains at you, you need the ctype.h library.

I don't see where numWords is initialized or assigned a value in main() or in readAndCount() before the ++ operator is called to increment it. Therefore, start with who knows what value and add one to it to gives who knows what value and end up outputting some irrational/illogical value for known input.

None of that still worked. Can't seem to stop the massive overcounting.

Post your exact code, the input you're giving the program, the output it's spitting out, your compiler, and your operating system.

This article has been dead for over six months. Start a new discussion instead.