The argc argument represents the number of arguments on the command line. The count includes the command name itself. The argv variable is a pointer to a pointer to a char. This sounds a bit abstract, but you can treat argv as if it were an array of pointers to the command-line arguments, with argv[0] being a pointer to the first character of a string holding the command name, argv[1] being a pointer to the first character of a string holding the first command-line argument, and so on. That is, argv[0] is the first string from the command line, and so on. For example, suppose you have the following command line:

wc report1 report2 report3

In this case, argc would be 4, argv[0] would be wc, argv[1] would be report1, and so on. The following loop would print each command-line argument on a separate line:

for (int i = 1; i < argc; i++)

       cout << argv[i] << endl;

Starting with i = 1 just prints the command-line arguments; starting with i = 0 would print the command name as well.

Command-line arguments, of course, go hand-in-hand with command-line operating systems such as the Windows command prompt mode, Unix, and Linux. Other setups may still allow you to use command-line arguments:

• Many Windows IDEs (Integrated Development Environments) have an option for providing command-line arguments. Typically, you have to navigate through a series of menu choices that lead to a box into which you can type the command-line arguments. The exact set of steps varies from vendor to vendor and from upgrade to upgrade, so check your documentation.

• Many Windows IDEs can produce executable files that run under in the Windows command prompt mode.

Listing 17.17 combines the command-line technique with file stream techniques to count characters in files listed on the command line.

Listing 17.17. count.cpp

// count.cpp -- counting characters in a list of files

#include

#include

#include    // for exit()

int main(int argc, char * argv[])

{

    using namespace std;

    if (argc == 1)          // quit if no arguments

    {

        cerr << "Usage: " << argv[0] << " filename[s]\n";

        exit(EXIT_FAILURE);

    }

    ifstream fin;              // open stream

    long count;

    long total = 0;

    char ch;

    for (int file = 1; file < argc; file++)

    {

        fin.open(argv[file]);  // connect stream to argv[file]

        if (!fin.is_open())

        {

            cerr << "Could not open " << argv[file] << endl;

            fin.clear();

            continue;

        }

        count = 0;

        while (fin.get(ch))

            count++;

        cout << count << " characters in " << argv[file] << endl;

        total += count;

        fin.clear();           // needed for some implementations

        fin.close();           // disconnect file

    }

    cout << total << " characters in all files\n";

    return 0;

}

Note

Some C++ implementations require using fin.clear() at the end of the program, and others do not. It depends on whether associating a new file with the ifstream object automatically resets the stream state. In does no harm to use fin.clear() even if it isn’t needed.

On a Linux system, for example, you could compile Listing 17.17 to an executable file called a.out. Then sample runs could look like this:

$ a.out

Usage: a.out filename[s]

$ a.out paris rome

3580 characters in paris

4886 characters in rome

8466 characters in all files

$

Note that the program uses cerr for the error message. A minor point is that the message uses argv[0] instead of a.out:

cerr << "Usage: " << argv[0] << " filename[s]\n";

This way, if you change the name of the executable file, the program will automatically use the new name.

The program uses the is_open() method to verify that it was able to open the requested file. Let’s examine that matter further.

File Modes

The file mode describes how a file is to be used: read it, write to it, append it, and so on. When you associate a stream with a file, either by initializing a file stream object with a filename or by using the open() method, you can provide a second argument that specifies the file mode:

ifstream fin("banjo", mode1);  // constructor with mode argument

ofstream fout();

fout.open("harp", mode2);      // open() with mode arguments

The ios_base class defines an openmode type to represent the mode; like the fmtflags and iostate types, it is a bitmask type. (In the old days, it was type int.) You can choose from several constants defined in the ios_base class to specify the mode. Table 17.7 lists the constants and their meanings. C++ file I/O has undergone several changes to make it compatible with ANSI C file I/0.

Table 17.7. File Mode Constants

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги