Jack Lorenzo Kurtz
Jack Lorenzo Kurtz

Reputation: 25

How to use the element of a string as a number

Write a program that takes an arbitrary number of file names as command line arguments and counts the frequency of each letter in the English alphabet (A through Z) appearing among all the files. Ignore all characters that are not part of the basic English alphabet. You should regard upper and lower case of the same letter as the same. Report the count of each letter, along with its overall frequency (as a percentage of total letters) to the user. You do not have to worry about letters with diacritical marks (e.g. umlauts) or other variants from the standard alphabet. (Rather than using many conditionals or switch, I suggest using a vector or map to store counts.)

I have most of the idea down, but once I am iterating through each individual character of the file, how do I add a count to the corresponding vector element? Here is my attempt at it but it is riddled with errors.

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

int main(int argc, char* argv[]){
    double total_letters = 0.0;
    vector<double> counts[26]={};
    if (argc == 1) {
        cout << "You did not enter any command line arguments!" << endl;
        return 0;
    }
    for(int i = 1; i <= argc - 1; i++){
        ifstream ifs(argv[i]);
        if (!ifs.is_open()){
            cout << "Error: file could not be opened." << endl;
            return 0;
        }
        string words = "";
        ifs >> words;
        for(int i = 0; i < words.size()-1; i++){
            if((tolower(words[i]) >= 97) && (tolower(words[i]) <= 122)){
                counts[(int)tolower(words[i]) - 97] = counts[(int)tolower(words[i]) - 97]+1;
            }
        }
        for(int i = 0; i < counts.size()-1; i++){
            total_letters = total_letters + counts[i];
        }
        ifs.close();
        ifs.clear();
    }
    for(int i = 0; i < counts.size()-1; i++){
        cout << endl << (char)i + 65 <<": " << counts[i] << ", " << ((double)counts[i]/total_letters)*100 << "%";
    }
    return 0;
}

Upvotes: 0

Views: 59

Answers (1)

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

You've made an array of vectors, rather than a simple vector. You should make the vector like this:

vector<double> counts('z'-'a'+1, 0);

'z'-'a'+1 is another way of writing 26. This way of writing the length of your vector leaves no doubts in reader's mind as to the purpose of the array (counting letters).

Now all you need to do is writing counts[index]++.

Note that hard-coding 97 and 122 should be avoided.

You need to read words in a loop. This line

ifs >> words;

reads a single word, not all words. The main loop should be as follows:

string word;
while (ifs >> word) {
    for (int i = 0 ; i != word.size() ; i++) {
        ch = word[i];
        if (!isalpha(ch)) {
            continue;
        }
        counts[tolower(ch)-'a']++;
    }
}

Upvotes: 1

Related Questions