I am writing 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) in all the files. Upper and lower case should be treated as the same letter. i want to report the count of each letter and its overall frequency (as a percentage of total letters). I think using a vector would be better than a bunch of conditionals but I don't know exactly how. This is what I have written so far. I would appreciate any corrections and help on how to use command line arguments in this way.
I do not know what you are using for command line arguments, so it is hard to be specific about what you could do. I do not work with command line arguments very often, but based on what I have seen this should give you an idea. Keep in mind that I have not tested this yet, but I think it is correct:
int main(int argc, char * argv[])
{
char getachar;
//int count[26]; // <--- Not needed.
std::vector<int> letters(26);
// check value of argc.
// print a message if to low
ifstream ifs(argv[1]);
while (ifs >> getachar)
{
for (int k = 0; k<26; k++)
{
if (getachaar == 'a' + k || getachar == 'A' + k)
{
letters[k]++;
}
}
}
}
Or
int main(int argc, char * argv[])
{
char getachar;
//int count[26]; // <--- Not needed.
std::vector<int> letters(26);
std::string inFileName{ argv[1]) };
std::string outFileName{ argv[2] };
// check value of argc.
// print a message if to low
ifstream ifs(inFileName);
while (ifs >> getachar)
{
for (int k = 0; k<26; k++)
{
if (getachaar == 'a' + k || getachar == 'A' + k)
{
letters[k]++;
}
}
}
}
You will also need a variable for "totalCharactersRead" or something like this and since you are doing a percentage at some point you will need to be working with "doubles" not "ints".
Include the header file "<cctype>" and you can use "std::tolower()" in your if statement: if (std::tolower(getachaar) == 'a' + k). This will make sure that each character is changed to a lower case letter before checking against "'a' + k" without changing the original character in the file.
#include <map>
#include <string>
#include <cctype>
#include <fstream>
#include <iostream>
void update_counts( std::istream& stm, std::map<char,int>& counts )
{
char c ;
while( stm >> c ) // for each non white-space character in the file
if( std::isalpha(c) ) // if it is an alphabetic character
++counts[ std::tolower(c) ] ; // increment the count (ignoring case)
}
int main( int argc, char* argv[] )
{
if( argc < 2 ) std::cout << "usage: " << argv[0] << " <file name> [<filename>]...\n" ;
else
{
std::map<char,int> counts ; // key: lower case character mapped value: frequency
for( int i = 1 ; i < argc ; ++i ) // for each command line argument
{
if( std::ifstream file{ argv[i] } ) // if a file with that name could be opened
{
std::clog << "process file '" << argv[i] << "'\n" ;
update_counts( file, counts ) ; // update the counts with characters read from the file
}
else std::cerr << "unable to open file '" << argv[i] << "'\n" ;
}
// print character counts
std::cout << "char frequency\n---- ---------\n" ;
for( constauto& pair : counts )
std::cout << pair.first << " " << pair.second << '\n' ;
}
}