CS 311 Fall 2024 > Assignment 8
CS 311 Fall 2024
Assignment 8
Assignment 8 is due at 5 pm Thursday, December 5. It is worth 60 points.
Procedures
This is, optionally, a group assignment. You may work in a group of two, if you wish. Each group only needs to turn in a single copy of the assignment. Under normal circumstances, each group member will receive the same grade on the assignment.
Turn in answers to the exercises below on the UA Canvas site, under Assignment 8 for this class.
- Your answers must consist of two files:
wordcount.cpp
, from Exercise A, andreverser_test.cpp
, from Exercise B. - I may not look at your homework submission immediately. If you have questions, e-mail me.
If you work in a group:
- The assignment files should contain the names of both group members.
- One student submits the assignment as usual, on Canvas.
- The other student submits an empty assignment (no attached source or header files) on Canvas, with a note indicating whom the assignment was done with.
Exercises (60 pts total)
Exercise A — Program: Counting Words
Purpose
In this exercise, you will write a program that uses a C++ STL Table implementation. Your program will also read information from a file. Robustness and proper error checking are an important part of the assignment.
Background
For the purposes of this exercise, a word is a contiguous sequence of one or more non-space characters.
For example, consider the following.
xyz/ xyz123 xyz xyz123 xyz abc
Four distinct words appear in the above text.
They are, in lexicographic order,
abc
, xyz
, xyz/
,
and xyz123
.
The words
xyz
and
xyz123
each appear twice.
The other words each appear once.
Instructions
Write a complete C++ program (including function main
!)
that inputs a filename from the user,
and reads the named file.
The program should then print
the number of distinct words that appear in the file,
followed by a list giving, for each word appearing,
the word itself and the number of times it appears in the file,
as shown below.
Be sure to follow the
coding standards.
All standards now apply!
- Store the source for your program in a single file:
wordcount.cpp
. - Your program must store its results, prior to printing, in an appropriate STL Table container.
- See the Testing section, below, for an example of the kind of output I am looking for.
- Your program should be robust. That is, it should never crash, no matter what the user types, and no matter what it finds in the file.
Testing
Since you are writing a complete program this time,
there will be no test program.
However, I have created a test input file:
wordcount_test.txt
.
(This file is also in the Git repository.)
If you run your program with this file as input,
then it should output the following.
Number of distinct words: 45 2024: 1 2024-11-21: 1 311: 1 8,: 1 A: 1 And: 1 Assignment: 1 CS: 1 Can: 2 Chappell: 1 Exercise: 1 Fall: 1 For: 1 G.: 1 Glenn: 1 Next: 1 Test: 1 What: 1 a: 3 again.: 1 change: 2 correctly: 2 count: 2 ending: 1 file: 2 for: 1 if: 1 input: 1 is: 2 it: 1 line-ending: 1 line.: 1 line?: 1 long: 2 marker?: 1 newline?: 1 no: 1 the: 1 there: 1 we: 2 when: 1 with: 1 word: 100000 wordcount_test.txt: 1 you: 2
Do not turn in wordcount_test.txt
.
Note that I may test your program using a different input file.
Hints
Using “
cin >> ...
” is almost never appropriate when reading from the user, because this reads individual words while users mostly think in terms of lines. Instead, usestd::getline
to grab a whole line at a time; then read from the string it gives you.- To check for errors when using C++ streams,
first use the “
!
” operator on the stream; then use member functioneof
.For example, if you have an
ifstream
calledinfile
, then after every operation oninfile
, you should do
This is a check for an error on the last operation. If this test succeeds (that is, if there was an error), and the operation was a read, then check for EOF next:if (!infile) { ...
if (infile.eof()) { ...
If this is true, then the error was due to the end of the file, and so there is nothing wrong with the file; just stop reading. On the other hand, if you get an error that is not due to EOF, then there is something wrong with the file or the device, or the connection to the device, etc.
- Robustness means that the user is allowed to do strange things,
and files are allowed to contain strange data,
but the program never behaves badly.
Test the strange cases. For example, what if the user, when prompted for a filename, just hits ENTER? What if they type a bunch of blanks and then hit ENTER? What about a filename with a blank in the middle? What about the name of a file that does not exist? A file that exists but cannot be read? An empty file? An executable file? a directory? Etc.
Exercise B — Writing a Test Suite
Purpose
In this exercise, you will write a test suite for a simple C++ class. You will use the doctest testing framework.
Background
Consider a class Reverser
.
And objects of this class is a function object
that takes two bidirectional iterators defining a range.
It reverses the order of the values in the range.
An object of type Reverser
might be used as follows.
[C++]
Reverser rr; deque<int> dd { 1.2, 5.2 }; rr(begin(dd), end(dd)); // Now dd contains 5.2, 1.2
A complete, correct definition of class Reverser
can be found in file reverser.hpp
,
in the Git repository.
Instructions
Modify the posted file reverser_test.cpp
so that it,
along with doctest.h
,
forms a thorough test program
for class Reverser
,
contained in header file reverser.hpp
.
- Your tests must use the doctest testing framework.
- Each
REQUIRE
directive (or other similar directive:REQUIRE_FALSE
, etc.) must have one or more associatedINFO
directives that give the user information for each failing test. - Your test suite must address all of the following
issues.
- Do both const & non-const
Reverser
objects work? - Does
Reverser
work properly for different data structures (e.g.,std::list
,std::deque
,std::vector
,std::array
,std::string
)? - Does
Reverser
work properly for different value types (e.g.,int
,double
,string
, etc.)? - Does
Reverser
work properly for empty ranges? For ranges of size 1? - Does
Reverser
work properly for very large ranges? - Is it clear that
Reverser
does not modify items just before or just after the range it is given? - When a test fails, is the message printed both correct and helpful?
- Do both const & non-const
- The compilation requirement in the coding standards,
as applied to this exercise,
means that your code must compile with
doctest.h
version 2 and a correctly written version ofreverser.hpp
.
Do not turn in files doctest.h
or reverser.hpp
.
Hints
- For the basics of writing a test suite using doctest, see the lecture slides for November 22.
- Write both correct and incorrect versions of
file
reverser.hpp
, and try out your test program with these.