Download code

Jump to: navigation, search

Back to Word_count_(C_Plus_Plus)

Download for Windows: single file, zip

Download for UNIX: single file, zip, tar.gz, tar.bz2

wc.cc

  1 /* The authors of this work have released all rights to it and placed it
  2 in the public domain under the Creative Commons CC0 1.0 waiver
  3 (http://creativecommons.org/publicdomain/zero/1.0/).
  4 
  5 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  6 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  7 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  8 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  9 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 10 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 11 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 12 
 13 Retrieved from: http://en.literateprograms.org/Word_count_(C_Plus_Plus)?oldid=10558
 14 */
 15 
 16 #include <cstdlib>
 17 #include <iostream>
 18 #include <ostream>
 19 #include <fstream>
 20 #include <cctype>
 21 #include <iomanip>
 22 #include <istream>
 23 struct option_struct
 24 {
 25   bool count_characters;
 26   bool count_words;
 27   bool count_lines;
 28   option_struct(): count_characters(false), count_words(false), count_lines(false) {}
 29 };
 30 class counter
 31 {
 32 public:
 33   counter(): characters(0), words(0), lines(0), current_is_whitespace(true) {}
 34   counter& operator+=(counter const& other)
 35   {
 36     characters += other.characters;
 37     words += other.words;
 38     lines += other.lines;
 39     return *this;
 40   }
 41   void update(char next_char);
 42   void report(option_struct options, char const* filename);
 43 private:
 44   int characters;
 45   int words;
 46   int lines;
 47   bool current_is_whitespace;
 48 };
 49 
 50 void counter::update(char next_char)
 51 {
 52     ++characters;
 53     if (next_char == '\n')
 54       ++lines;
 55     bool next_is_whitespace = std::isspace((unsigned char)next_char);
 56     if (current_is_whitespace && !next_is_whitespace)
 57       ++words;
 58     current_is_whitespace = next_is_whitespace;
 59 }
 60 
 61 void counter::report(option_struct options, char const* filename)
 62 {
 63   if (options.count_lines)
 64     std::cout << std::setw(7) << lines << " ";
 65   if (options.count_words)
 66     std::cout << std::setw(7) << words << " ";
 67   if (options.count_characters)
 68     std::cout << std::setw(7) << characters << " ";
 69   if (filename)
 70     std::cout << filename;
 71   std::cout << std::endl;
 72 }
 73 void print_error(char const* context, char const* message)
 74 {
 75   std::cerr << "wc: ";
 76   if (context)
 77     std::cerr << context << ": ";
 78   std::cerr << message << std::endl;
 79 }
 80 bool process_file(std::istream& file, char const* filename, counter& total, option_struct options)
 81 {
 82   if (!file)
 83   {
 84     print_error(filename, "failed to open.");
 85     return false;
 86   }
 87   file >> std::noskipws;
 88   char c;
 89   counter result;
 90   while (file >> c)
 91     result.update(c);
 92   if (!file.eof())
 93   {
 94     print_error(filename, "reading failed.");
 95     return false;
 96   }
 97   result.report(options, filename);
 98   total += result;
 99   file.clear();
100   return true;
101 }
102 int main(int argc, char* argv[])
103 {
104   int exit_code = EXIT_SUCCESS;
105   int current_arg = 1;
106   option_struct options;
107   while(current_arg < argc
108         && argv[current_arg][0] == '-'
109         && argv[current_arg][1] != '\0')
110   {
111     char* arg = argv[current_arg];
112     for (std::size_t position = 2; arg[position] != '\0'; ++position)
113     {
114       switch(arg[position])
115       {
116       case 'c':
117         options.count_characters = true;
118         break;
119       case 'w':
120         options.count_words = true;
121         break;
122       case 'l':
123         options.count_lines = true;
124         break;
125       default:
126         std::cerr << "wc: invalid option: " << arg[position] << "\n";
127         return EXIT_FAILURE;
128       }
129     }
130   }
131   if (!(options.count_characters || options.count_words || options.count_lines))
132     options.count_characters = options.count_words = options.count_lines = true;
133   counter total;
134 
135   if (current_arg == argc)
136   {
137     if (!process_file(std::cin, NULL, total, options))
138       exit_code = EXIT_FAILURE;
139   }
140   else
141   {
142     for (int file_arg = current_arg; file_arg < argc; ++file_arg)
143     {
144       char const* filename = argv[file_arg];
145       if (filename[0] == '-' && filename[1] == '\0')
146       {
147         if (!process_file(std::cin, filename, total, options))
148           exit_code = EXIT_FAILURE;
149         std::cin.clear();
150       }
151       else
152       {
153         std::ifstream file(filename);
154         if (!process_file(file, filename, total, options))
155           exit_code = EXIT_FAILURE;
156       }
157     }
158   }
159   if (argc - current_arg > 1)
160     total.report(options, "total");
161   return exit_code;
162 }
163 


hijacker
hijacker
hijacker
hijacker