1. Homepage of Dr. Zoltán Porkoláb
    1. Home
    2. Archive
  2. Teaching
    1. Timetable
    2. Bolyai College
    3. C++ (for mathematicians)
    4. Imperative programming (BSc)
    5. Multiparadigm programming (MSc)
    6. Programming (C in English)
    7. Programming languages (PhD)
    8. Software technology lab
    9. Theses proposals (BSc and MSc)
  3. Research
    1. CodeChecker
    2. CodeCompass
    3. Templight
    4. Projects
    5. Publications
    6. PhD students
  4. Affiliations
    1. Dept. of Programming Languages and Compilers
    2. Ericsson Hungary Ltd

Practice 12.

wcount as a Unix utility

In the Practice 4 we implemented a simple wcount program to count the number of newlines, words and characters reading from the standard input. However, real Unix utilities are more complex, they can read from files given as command line parameters. In this practice, we will implement such a version of wcount.

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
//
// wcount -- similar to unix wc command
// counts newlines, words and characters
// v2. reading from standard input or from files
//

#include <iostream>
#include <fstream>    // for std::ifstream
#include <iomanip>    // for std::setw
#include <cctype>     // for std::isspace
#include <cerrno>     // for std::errno
#include <cstring>    // for std::strerror
#include <clocale>    // for std::setlocale

// this function will do the actual job for a single file
void wcount(std::istream &inp, std::string filename);

// this variables will collect the summary information 
int slcount = 0; // sum newlines
int swcount = 0; // sum words
int sccount = 0; // sum characters

int main(int argc, char*argv[])
{
  int exit_code = 0; // exit code of process 
                     //  0 == no error, 
                     //  1 == at least one file failed 
  if ( argc < 2 ) // no parameter: read from cin
  {
    wcount( std::cin, "");  
  }	  
  else            // there are filename parameters 
  {     
    for ( int i = 1; i < argc; ++i)
    {
      std::ifstream inp(argv[i]);
      if ( inp )   // open succesful
      {
        wcount( inp, argv[i]);	      
      }      
      else         // open failed
      { 
        // set the language to locale
	std::setlocale(LC_ALL, "hu_HU.utf8");
        // convert readable error message from errno
	std::cerr << argv[i] << ": " 
                  << std::strerror(errno) << '\n';
	exit_code = 1;
      }	      
    }	
    if ( argc > 2 )  // more than 1 files: write summary
    {
      std::cout << std::right << std::setw(6) << slcount 
         << " " << std::right << std::setw(6) << swcount 
         << " " << std::right << std::setw(6) << sccount
         << " \tsummary" << '\n';
    }
  }
  return exit_code;  // for the operating system
}

// counting one file or cin until EOF
void wcount(std::istream &inp, std::string filename)
{
  int lcount = 0; // newlines
  int wcount = 0; // words
  int ccount = 0; // characters

  char ch;          // current character to read in
  char prev = '\n'; // previous char for wcount initialized 
                    // to whitespace for the very first word 
                    // at the beginning of the input

  inp >> std::noskipws; // otherwise operator>> skips 
                        // whitespace characters

  while ( inp >> ch )   // true until reading fails
  {
    ++ccount;	  
    if ( '\n' == ch ) ++lcount;  // literal on the left
    if ( std::isspace(prev) && !std::isspace(ch) ) ++wcount;
    prev = ch;
  }
  // print results for this file
  std::cout << std::right << std::setw(6) << lcount 
     << " " << std::right << std::setw(6) << wcount
     << " " << std::right << std::setw(6) << ccount
     << " \t" << filename << '\n';
  // update summary
  slcount += lcount; 
  swcount += wcount;
  sccount += ccount;
}

The program can be tested against the standard input or given one or more filename parameters. If any of filename parameters missing an error message should appear on standard error.

$ g++ -Wall -Wextra wcount2.cpp -o wcount
$ ./wcount < wcount2.cpp 
    83    344   2218 
$ ./wcount wcount1.cpp wcount2.cpp
    31    146    873 	wcount1.cpp
    83    344   2218 	wcount2.cpp
   114    490   3091 	summary
$ ./wcount wcount1.cpp nonexist.cpp wcount2.cpp
    31    146    873 	wcount1.cpp
nonexist.cpp: Nincs ilyen fájl vagy könyvtár
    83    344   2218 	wcount2.cpp
   114    490   3091 	summary

Financed from the financial support ELTE won from the Higher Education Restructuring Fund of the Hungarian Government.