CS253 HW5: Operations!                
Changes                
Updates to the assignment will be noted here. None yet!
                
Description                
Surprisingly, management is delighted with your work in HW3.
Unsurprisingly, they want more. One could argue that they’ve gone
way overboard, but that’s management. For this assignment, you will
improve your class Words
from HW3, adding several operations.
                
Methods                
Words
must have all the required methods (including no default ctor)
and operations from HW3, and:
                
-
Words + Words
-
Combine the words from the two objects. For example,
Words("a dog") + Words("is your\\ friend")
will yield a Words
object containing the same four words, and the same escaped flags,
in the same order, that
Words("a dog is your\\ friend")
would produce.
This operation must not change either of its operands.
-
Words += Words
-
Add all the words in the second object to the end of the first object.
For example, after
Words w("a b"), x("c d"); w += x;
the object w
would contain the four words a
, b
, c
, and
d
, in that order.
The escapedness of the words are also copied.
This operation must not change the second object.
This operation must return a reference to the first object.
-
Words == Words
-
Return true iff the two objects contain exactly
the same words, in the same order. Escapedness does not matter.
-
Words != Words
-
Return false iff the two objects contain exactly
the same words, in the same order. Escapedness does not matter.
- Boolean context
-
Evaluating a
Words
object in boolean context will return true
iff its .size()
is more than zero.
- predecrement
-
Predecrementing a
Words
makes each of its words shorter, by
removing the last byte. A string that was already zero-length will
be removed from the object. Escapedness must be preserved, even if
the character that was escaped is deleted.
A reference to the modified object is returned.
- postdecrement
-
Has the same effect on the object as predecrement, but returns
the old value (by value), not the new value.
-
Words[size_t]
-
The subscript operation must return a struct that contains the two
values returned by
.get()
, given the same index. The struct
must have a .first
member that contains the string for the word,
and .second
member that contains true iff
the word was escaped.
If the index is out of range, throw an std::out_of_range error,
whose message must contain the erroneous index, and the .size()
of the Words
object.
The types and names in the descriptions, above, do not
determine the C++ declarations of those methods. They only serve to
informally describe what sort of arguments a method might take.
                
Const-correctness, for arguments and operators, is your job.
For example, it must be possible use +
on two const Words
objects, to use []
on a const Words
.
                
You may define other methods or data, public or private, as you see fit.
You may define other classes, as you see fit. However, to use the
Words
class, the user need only #include "Words.h"
, not any
other header files.
                
Debugging                
If you encounter “STACK FRAME LINK OVERFLOW”, then try this:
export STACK_FRAME_LINK_OVERRIDE=ffff-ad921d60486366258809553a3db49a4a
Sample Run                
Here is a sample run, where %
is my shell prompt:
                
% cat CMakeLists.txt
cmake_minimum_required(VERSION 3.11)
project(hw5)
# Are we in the wrong directory?
if(CMAKE_SOURCE_DIR MATCHES "[Hh][Ww]([0-9])$")
if(PROJECT_NAME MATCHES "[^${CMAKE_MATCH_1}]$")
message(FATAL_ERROR "Building ${PROJECT_NAME} in ${CMAKE_SOURCE_DIR}")
endif()
endif()
# Using -Wall is required:
add_compile_options(-Wall)
# These compile flags are highly recommended, but not required:
add_compile_options(-Wextra -Wpedantic)
# Optional super-strict mode:
add_compile_options(-fmessage-length=80 -fno-diagnostics-show-option
-fstack-protector-all -g -O3 -std=c++17 -Walloc-zero -Walloca
-Wctor-dtor-privacy -Wduplicated-cond -Wduplicated-branches
-Werror -Wextra-semi -Wfatal-errors -Winit-self -Wlogical-op
-Wold-style-cast -Wshadow -Wunused-const-variable=1
-Wzero-as-null-pointer-constant)
# add_compile_options must be BEFORE add_executable.
# Create the executable from the source file main.cc:
add_library(${PROJECT_NAME} Words.cc)
add_executable(test test.cc)
target_link_libraries(test ${PROJECT_NAME})
# Create a tar file every time:
add_custom_target(${PROJECT_NAME}.tar ALL COMMAND
tar -cf ${PROJECT_NAME}.tar *.cc *.h CMakeLists.txt)
% cmake . && make
… cmake output appears here …
… make output appears here …
% cat test.cc
#include "Words.h"
#include "Words.h" // I meant to do that.
#include <iostream>
#include <cassert>
using namespace std;
int main() {
Words a("");
assert(a.size() == 0);
assert(a.empty());
assert(!a);
a.analyze("Applejack Pinkie\\ Pie");
assert(a.size() == 2);
assert(a);
auto p = a[0];
assert(p.first == "Applejack" && !p.second);
p = a[1];
assert(p.first == "Pinkie Pie" && p.second);
assert(a == Words("\v\\Applejack\nPinkie\\ Pie \f\t\r"));
assert(a != Words("Applejack Pinkie\\ Pie ajbaxah"));
assert(!(a != Words("Applejack Pinkie\\ Pie")));
assert(!(a == Words("Applejack Pinkie\\ Pie ffff")));
const Words b(" Fluttershy "), c(" Rarity "), d(b+c);
assert(b.size() == 1);
assert(c.size() == 1);
assert(d.size() == 2);
Words e(a += d);
assert(a == e);
assert(e.size() == 4);
assert(e[0].first == "Applejack");
assert(e[1].first == "Pinkie Pie");
assert(e[2].first == "Fluttershy");
assert(e[3].first == "Rarity");
assert(!e[0].second);
assert( e[1].second);
assert(!e[2].second);
assert(!e[3].second);
while (e) {
cout << "size=" << e.size() << " ";
cout << e-- << '\n';
}
cout << "Done.\n";
return 0;
}
% ./test
size=4 Applejack,Pinkie Pie,Fluttershy,Rarity
size=4 Applejac,Pinkie Pi,Fluttersh,Rarit
size=4 Appleja,Pinkie P,Flutters,Rari
size=4 Applej,Pinkie ,Flutter,Rar
size=4 Apple,Pinkie,Flutte,Ra
size=4 Appl,Pinki,Flutt,R
size=4 App,Pink,Flut,
size=3 Ap,Pin,Flu
size=3 A,Pi,Fl
size=3 ,P,F
size=2 ,
Done.
Hints                
- “How am I supposed to allocate space for the return value of
+
without using dynamic memory?” Consider a function that adds two
integers and returns the result. Does that function need dynamic
memory?
- I’ve given you several
examples of classes with operators.
You might want to look at them.
- Keep your operators DRY.
- Removing an item from a container while you’re looping over it
is like painting the floor you’re standing on.
Libraries                
libhw5.a
is a library file. It contains a number of *.o
(object) files. It must contain Words.o
, but it may also contain
whatever other *.o
files you need. The CMakeLists.txt
shown
creates libhw5.a
. It does not contain main().
                
Testing                
You will have to write a main() function to test your code. Put it
in a separate file, and do not make it part of libhw5.a
.
Particularly, do not put main() in Words.h
or
Words.cc
. You will also have to create Words.h
, and put it into
hw5.tar
. We will test your program by doing something like
this:
                
mkdir a-new-directory
cd the-new-directory
tar -x </some/where/else/hw5.tar
cmake . && make
cp /some/other/place/test-program.cc .
g++ -Wall test-program.cc libhw5.a
./a.out
We will supply a main program to do the testing that we want.
You should do something similar. It’s your choice whether to
include your test program in your hw5.tar
file.
However, cmake . && make
must work. If it fails
because you didn’t package test.cc
, but your CMakeLists.txt
requires test.cc
, then your build failed, and you get no points.
Test your tar file, not just your code.
                
Requirements                
The HW3 requirements all apply.
                
Tar file                
- The tar file for this assignment must be called:
hw5.tar
- It must contain:
- source files (
*.cc
), including Words.cc
- header files (
*.h
), including Words.h
CMakeLists.txt
, which will create the library file
libhw5.a
.
- These commands must produce the library lib
hw5.a
:
cmake . && make
- Your
CMakeLists.txt
must use at least -Wall
when compiling.
How to submit your work:                
In Canvas, check in the
file
hw5.tar
to the assignment “HW5”.
It’s due 10:00:00ᴘᴍ MT Saturday, with a 24-hour late period for a 25% penalty.
                
How to receive negative points:                
Turn in someone else’s work.