Accelerated C++ Solution to Exercise 4-5

Exercise 4-5

Write a function that reads words from an input stream and stores them in a vector. Use that function both to write programs that count the number of words in the input, and to count how many times each word occurred.

Solution

This is a somewhat simplified version of Solution to Exercise 4-0, in the sense that 4-0 processes the std::vector<Student_Info> container, whereas 4-5 deals processes the std::vector<std::string> container.

Solution Strategy

  1. Create a readWords function to parse individual std::string objects (i.e. words) to a std::vector<std::string> container wordList. We can reuse the skeleton logic from the std::istream& read_hw function defined in the Solution to Exercise 4-0.
  2. The word count is essentially the number of elements within the wordList container. i.e. wordList.size(). Though not strictly neccessary, I have created a function called countWords which does the same thing.
  3. Create a countUniqueWords function to calculate the number of unique words within the container. We can reuse the skeleton logic from the Solution to Exercise 3-3.
  4. Invoke these functions via the main program.

The Project

As usual, I partition the program into smaller chunks – i.e. in C++ source files and header files.

C++ Source Files

  • main.cpp – this is the first program that is run during the implementation phase.
  • readWords.cpp – contains all functions relating to creating and processing the std::vector<std::string> container.

C++ Header Files

  • readWords.h– declare the functions as defined in readWords.cpp.

This diagram below shows what the Code::Block Management Tree look like after successful creation of these files.

Acpp4p5MgntTree

Source Files

main.cpp

#include <iostream>
#include "readWords.h"

using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;

int main()
{
    vector<string> wordList;
    readWords(cin, wordList);
    displayWords(wordList);
    cout << "No. Words = " << countWords(wordList) << endl;
    cout << "No. Unique Words = " << countUniqueWords(wordList) << endl;
    return 0;
}

readWords.cpp

#include "readWords.h"
#include <algorithm>

using std::vector;
using std::string;
using std::istream;
using std::cout;
using std::endl;
using std::sort;

// read string objects one-by-one, and append to a vector<string> container
// note: I reuse the Student_info.cpp from the Solution to Exercise 4-0
istream& readWords(istream& in, vector<string>& words)
{
    if (in)
    {
        // get rid of previous contents
        words.clear();

        // read input string one by one, and append to vector<string> container
        string x;
        while (in >> x)
            words.push_back(x);

        // clear the stream error status (if any) so that input will work for the next set of inputs
        in.clear();
    }
    return in;
}

// function to display the elements within the vector<string> container
int displayWords(const vector<string>& words)
{
    for (vector<string>::size_type i = 0; i != words.size(); ++i)
        cout << words[i] << endl;
    return 0;
}

// function to count elements within a vector<string> container
int countWords(const vector<string>& words)
{
    return words.size();
}

// function to count unique elements within a vector<string> container
// note: borrowed from the solution to exercise 3-3
int countUniqueWords(const vector<string>& words)
{
    vector<string> tmpWords = words;

    typedef vector<string>::size_type vec_sz;
    const vec_sz numElements = tmpWords.size();

    if (numElements == 0) return 0;
    else if (numElements == 1) return 1;

    sort(tmpWords.begin(),tmpWords.end());
    const vec_sz numLoops = numElements - 1;

    vec_sz A = 0;
    vec_sz B = 1;
    int numUniqueWords = 1;
    for (vec_sz i = 0; i != numLoops; ++i)
    {
        if (tmpWords[B] != tmpWords[A])
            ++numUniqueWords;
        ++A;
        ++B;
    }
    return numUniqueWords;
}

Header Files

readWords.h

#ifndef GUARD_READWORDS_H
#define GUARD_READWORDS_H

#include <iostream>
#include <vector>
#include <string>

std::istream& readWords(std::istream&, std::vector<std::string>&);
int displayWords(const std::vector<std::string>&);
int countWords(const std::vector<std::string>&);
int countUniqueWords(const std::vector<std::string>&);

#endif // GUARD_READWORDS

Result

Test 1 – Supply 0 Words

^Z
No. Words = 0
No. Unique Words = 0

Test 2 – Supply 1 Word

aaa
^Z
aaa
No. Words = 1
No. Unique Words = 1

Test 3 – Supply Multiple Words

aaa bbb ccc ddd aaa bbb aaa
^Z
aaa
bbb
ccc
ddd
aaa
bbb
aaa
No. Words = 7
No. Unique Words = 4

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Leave a reply