This is Part 2 of the 3-part Solution to Exercise 5-0.
Exercise 5-0 (Part 2 / 3)
This is a very simple program with the purpose of splitting a line of text (i.e. a input string) into words (i.e. an output vector<string>).
The Problem
Start from scratch, we need to write a program that is able to read in a line of text, and be able to split it into words. The full description and explanation of the program can be found in Chapter 5 of the book.
Solution Strategy
The text book sample program for this (part 2) exercise is fairly simple. It only requires 3 files which I can group into a small project as usual – I will describe this in the Project section below.
There is also one core learning from this chapter regarding sequential container processing using either (1) index, or (2) iterator. Both methods are effectively the same. e.g. assuming v is a vector<string>, the two following codes have the same effect (of displaying container elements to the output console).
Sequential Container Processing with Index:
for (vector<string>::size_type i = 0; i != v.size(); ++i) cout << v[i] << endl;
Sequential Container Processing with Iterator:
for (vector<string>::const_iterator iter = v.begin(); iter != v.end(); ++iter) cout << (*iter) << endl;
Remark
As the Author mentioned in the book, however:
- Index is good for random container processing, whereas
- Iterator is good for sequential container processing.
It is always a good idea to bear this in mind.
The Project
This is what the management tree looks like in Code::Block:
C++ Source Files
- main.cpp – this is the first program that is run during the implementation phase.
- split.cpp – contains the split function.
C++ Header Files
- split.h – declare the functions in the source file split.cpp.
Source Files
main.cpp
#include <iostream> // cin, cout, endl, getline #include <vector> // vector #include <string> // string #include "split.h" // split using std::vector; using std::string; using std::cin; using std::cout; using std::endl; using std::getline; // (5.7/90) int main() { string s; // read and split each line of input while (getline(cin, s)) { vector<string> v = split(s); // write each word in v for (vector<string>::const_iterator iter = v.begin(); iter != v.end(); ++iter) cout << (*iter) << endl; } return 0; }
split.cpp
#include <string> // string #include <vector> // vector #include <cctype> // isspace using std::vector; using std::string; using std::isspace; // scan a string of texts, split into words, return a vector that contains these words. // (S5.6/88) vector<string> split(const string& s) { vector<string> ret; typedef string::size_type string_size; string_size i = 0; // invariant: we have processed characters original value of [i, i) while (i != s.size() ) { // ignore leading blanks // invariant: characters in range [original i, current i) while (i != s.size() && isspace(s[i])) ++i; // find end of next word string_size j = i; // invariant: none of the characters in range [original j, current j) is a space while (j != s.size() && !isspace(s[j])) ++j; // if we found some non-whitespace characters if (i != j) // copy from s starting at i and taking j - i chars ret.push_back(s.substr(i, j - i)); i = j; } return ret; }
Header Files
split.h
#ifndef GUARD_SPLIT_H #define GUARD_SPLIT_H #include <vector> #include <string> std::vector<std::string> split(const std::string&); #endif // GUARD_SPLIT_H
Test Results
I am going to enter the following 3 lines when the program starts up. I should see the individual words (separated by empty space) displayed on the screen straight after I hit the enter button.
- Hello world, how are we today?
- Nice, so the program works!
- Bye bye
Hello world, how are we today? Hello world, how are we today? Nice, so the program works! Nice, so the program works! Bye bye Bye bye ^Z
The program works as expected!