// 1.	Find the frequencies of individual letters in a sample
//		text file.
// 2.	Display this information both numerically and graphically. 
//		a) In A..Z sequence
//		b) In decreasing frequency sequence
// Programming concepts and C++ Language elements used
// a) vector of structs, b) sorting

#include <iostream>
#include <string>
#include <iomanip>
#include <cctype>
#include <fstream>
#include <vector>
using namespace std;

// global constant for the size of the alphabet
const int AlphabetSize = 26;

struct FreqInfo {
	char letter;	// a letter of the alphabet
	int count;		// its frequency (the number of times it appears)
}; // end freqInfo

// function prototypes
void printChars (int n, char c = '*');	// our old friend
int char2int(char arg);
void display(const vector<FreqInfo> & vec);
void sort(vector<FreqInfo> & vec);	// sort the vector (decreasing count)

// function to store all letters and set the corresponding counts to 0
void init(vector<FreqInfo> & vec);	

int main() {
	// output identification
	cout << "CPS 150 Assignment 11 by Brian Turk \n\n";       

	// variables needed
	// vector of (Letter, Count) pairs
	vector<FreqInfo> LtrCounts(AlphabetSize);	
	ifstream fin;		// input file stream
	string fileName;	// input file's external name
	char ch;	// to hold a character read from file
	int code;	// to hold integer code corresponding to a character
	int count[AlphabetSize]={0};
	

	// prompt for the file name and get it
	cout << "Enter the file name: " ;	cin >> fileName ;

	// abort if file could not be opened
	fin.open(fileName.c_str());
	if (!fin) {
		cout << "\nCould not open " << fileName << " aborting run\n\n";
		return 1;
	} // end if

	init(LtrCounts);	// put the letters 'A'..'Z' in the vector and 
						// initialize the counts to 0

	
	// run this loop until attempt to read a character from the file fails
	while( fin>>ch ) {
		// get the integer code for the character by calling char2int
		code = char2int(ch) ;

		// if code is between 0 and (AlphabetSize - 1) then the character was 
		// a letter so increment the corresponding counter (Be clever now!)
		if ( code>=0 && code<AlphabetSize ) {
			count[code-1]+=1;
		} 
	} // end while
	

	cout << "The letter frequencies in alphabetic order\n\n";

	// call display function to display the counters
	display(LtrCounts) ;

	// call sort function to sort the vector
	sort(LtrCounts) ;

	cout << "\nThe letter frequencies in decreasing order\n\n";
	
	// call display function to display the counters again
	display(LtrCounts) ;

	cout << "\n\nAssignment 11 complete\n\n";
	return 0;
} // end main

// function printChars writes n copies of the character c to the
// standard output device
void printChars (int n, char c) {
	for (int k = 1; k <= n; k ++)
		cout << c;
} // end printChars

// function char2int returns an integer code depending on its
// parameter. If the parameter is a letter then a value between 0 and
// 25 is returned (0 for A, 1 for B, ..., 25 for Z).
// If the parameter is not a letter, then -1 is returned
int char2int(char arg) {
	if (!isalpha(arg))
		return -1;

	// arg is a letter, convert to upper case
	arg = toupper(arg);
	return static_cast<int>(arg) - static_cast<int>('A');
} // end char2int

// store all letters and set the corresponding counts to 0
void init(vector<FreqInfo> & vec) {
	for (int k = 0; k < AlphabetSize; k++) {
		vec[k].count = 0;
		vec[k].letter = static_cast<char>(k + static_cast<int>('A'));
	} // end for
} // end init

// function display displays the counters and letters from the vector
void display(const vector<FreqInfo> & vec) {
	for (int k = 0; k < vec.size(); k++) {
		
		// display the letter corresponding to k 
		cout << vec[k].letter << ':';

		// display numer96ical value of the counter corresponding to k
		cout << setw(3) << vec[k].count << ' ';

		// call printChars to display properly sized bar
		printChars(vec[k].count,'*');

		// end the line
		cout << endl;
	} // end for
} // end display

// This function sorts the vector in decreasing order of the counts.
void sort(vector<FreqInfo> & vec) {
	// Use Bubble sort as it is stable, Selection sort is not stable
	bool swapped = true;
      int j = 0;
      int tmp;
      while (swapped) {
            swapped = false;
            j++;
            for (int i = 0; i < AlphabetSize - j; i++) {
                  if (vec[i].count > vec[i + 1].count) {
                        tmp = vec[i].count;
                        vec[i].count = vec[i + 1].count;
                        vec[i + 1].count = tmp;
                        swapped = true;
                  }
            }
      }
	


} // end sort

This is the program I am writing with the skeleton of my professor. I am not sure how to pass the count into the vector and I have been at it for day. Please any help would be greatly appreciated.

Recommended Answers

All 5 Replies

Use the .push_back() method of the vector.

Why are you bothering to write your own sort instead of using std::stable_sort?

Use the .push_back() method of the vector.

I thought that push back was for adding values to the end of a vector. I am trying to make a counter for how many times a character is used in a txt file. Would that still work?

I was assuming you'd go through and count all of the 'a's and 'A's, write that into a struct, push the struct into the vector, etc.

You need some code between lines 72 and 75 to actually populate your vector with the information that you have about the letter counts. This is where the std::vector::push_back() method that jonsca is talking about would come in. So, you'd have some loop that looked like:

for(int i = 0; i < alphabetSize; i++){
   FreqInfo temp_freqInfo = {static_cast< char >(i + static_cast< int >('A')), count[i]};
   LtrCounts.push_back(temp_freqInfo);
}

However, you already declare LtrCount to be big enough to hold your alphabet at the start, so you don't need to do that here (although it would be a good way if you didn't know the alphabet size in advance). Since you've done this, and used your init() function to initialise all the counts to 0, you can increment them directly, using something like:

LtrCount.at(code).count++;

so you don't need a separate count array or the extra loop between line 72 and 75.

Also, do you mean line 70 to be:

count[code-1]+=1;

since, code is looping from 0 to alphabetSize then you will try and write to count[-1] , which is not good!

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.