command line arguments w an arbitrary number of files

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <vector>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char * argv[]){
    char getachar;
    int count[26];
    ifstream ifs (....);
    while (ifs >> getachar){
    for(int k = 0; k<26; k++){
        if(getachaar == 'a'+k || getachar == 'A'+k){
            count[k]++;
            }
        }
    }
}
Hello shimshim96,

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:

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
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.

I will test this out a little later.

Hope that helps for now,

Andy
Avoid making naive assumptions about how alphabetic characters are encoded.

To check if a character is an alphabetic character, use std::isalpha
http://en.cppreference.com/w/cpp/string/byte/isalpha
To convert an alphabetic character to its lower case counterpart, use std::tolower
http://en.cppreference.com/w/cpp/string/byte/tolower

Something like this, perhaps:
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
#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( const auto& pair : counts )
            std::cout << pair.first << "    " << pair.second << '\n' ;
     }
}
Topic archived. No new replies allowed.