14.7.2. wc2.cpp: Character I/O Example

Review

The wc2 example relies on concepts and examples introduced previously. Please review the following as needed:

The word count utility, wc, has been included in most POSIX operating systems (Unix, Linux, and macOS) from their earliest days. We used a simplified version of wc in chapter 3 as a switch-statement example. We restore some of the removed functionality in this version, allowing users to enter multiple file names on the command line. The program will print count totals for all files.

This example demonstrates a situation where creating a single input stream object is convenient. The program alternately opens and closes the stream to process multiple files.

Program Listing

#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;

int main(int argc, char* argv[])             // (a)
{
    ifstream file;                           // (b)
	
    int     total_chars = 0;                 // (c)
    int     total_lines = 0;
    int     total_words = 0;

    for (int i = 1; i < argc; i++)           // (d)
    {
        file.open(argv[i]);                  // (e)

        if (! file.good())                   // (f)
            continue;

        int    chars = 0;                    // (g)
        int    lines = 1;
        int    words = 0;
        bool   in_word = false;
        int    c;

        while ((c = file.get()) != EOF)      // (h)
        {
            chars++;

            switch (c)
            {
                case '\n':
                    lines++;
                    // fall through
                case ' ':
                case '\t':
                    in_word = false;
                    break;
                default:
                    if (! in_word)
                    {
                        in_word = true;
                        words++;
                    }
                    break;
            }
        }

        file.close();                        // (i)

        total_chars += chars;                // (j)
        total_lines += words;
        total_words += lines;

        cout << setw(8) << lines <<          // (k)
            setw(8) << words <<
            setw(8) << chars <<
            " " << argv[i] << endl;
    }

    if (argc > 2)                            // (l)
        cout << setw(8) << total_lines <<
            setw(8) << total_words <<
            setw(8) << total_chars <<
            " total" << endl;

    return 0;
}
  1. File names are accessed through argc and argv.
  2. Instantiates an input file stream object named file that can read the contents of a file but does not open a file
  3. The accumulators for counting the total characters, lines, and words in all the files named on the command line.
  4. The for-loop processed the files named in the command line arguments one at a time.
  5. Opens a file that can be read with the input stream object.
  6. Skips files that fail to open correctly by continuing with the next iteration of the for-loop. Notice the ! operator.
  7. The per file accumulators, the flag, and an input variable used to process each file.
  8. The get function reads one character from the file and stores it in the variable c. Please see the original wc.cpp example for details about this part of the program.
  9. Closes the input file but doesn't destroy the stream object, which is reused in the next iteration of the for-loop.
  10. Updates the total counts with the file counts.
  11. Prints the file counts followed by the file name.
  12. If there were multiple files named on the command line, then print the totals for all files.
wc2.cpp. A single instance of ifstream is created and used to process multiple files. Each file is opened at the top of the for-loop and closed at the bottom. An open file uses some system resources so it's important to close the file after processing it to release those resources. The nested while-loop counts the lines, words, and characters in each file; the program prints total counts for all files at the bottom following the for-loop.

Downloadable File

wc2.cpp