labs

c2cpp lab3: Mdb with Classes

This assignment is worth 200 points total.

Please read this assignment carefully and follow the instructions EXACTLY.

Submission

Do NOT create any additional subdirectories. Work inside the existing part*/ subdirectories.

Note that certain part*/ directories contain symlinks (“symbolic links”) to files from previous parts; this simply indicates that the file is the same as before, and that there’s no need to modify it further.

Ensure the Makefile for each part builds all executables when you run make.

Please refer to the lab submission instruction for other requirements.

Please check your code with valgrind. You will be penalized if you have any memory leaks or errors.

Part 0: Mdb without classes

Take a look in the part0/ directory at the provided C programs mdb-add.c and mdb-cat.c. Feel free to build them and test them; make sure you understand what they do and how they work. These are available as a reference for subsequent parts.

There’s nothing to submit for this part.

Example usage

$ ./mdb-add mdb
name please (will truncate to 15 chars): new
msg please (will truncate to 23 chars): msg
   1: {new} said {msg}
$ ./mdb-add mdb
name please (will truncate to 15 chars): cool
msg please (will truncate to 23 chars): msg
   2: {cool} said {msg}
$ ./mdb-add mdb
name please (will truncate to 15 chars): jae woo
msg please (will truncate to 23 chars): mii
   3: {jae woo} said {mii}
$ ./mdb-cat mdb
   1: {new} said {msg}
   2: {cool} said {msg}
   3: {jae woo} said {mii}

Part 1: Implementing an Mdb class

Work from the part1/ directory for this part.

The skeleton code contains completed mdb-add.cpp and mdb-cat.cpp programs which make use of the uncompleted class Mdb in mdb.h. Implement this class so that mdb-add and mdb-cat work correctly, like their C counterparts from Part 0 (with a few caveats, to be addressed in Part 2).

Requirements

Hints

Part 2: Extending our use cases

Work from the part2/ directory for this part.

Part 2a: Splitting the Mdb class

Assuming all went well in Part 1, your class Mdb implementation likely works fine for the average database file. But upon closer inspection, it’s evident that this model is a bit too inflexible; our Mdb constructor assumes the specified database file may be used for both reading and writing, so if we need to open a read-only file with mdb-cat, for example, this will fail despite that our intent is only to read. You may confirm this for yourself with chmod -w some_mdb ; ./mdb-cat some_mdb.

To remedy this, you’re going to split Mdb’s reading and writing functionality into two separate classes MdbReader and MdbWriter, and have Mdb inherit from both of these.

   MdbReader   MdbWriter
        \         /
         \       /
          \     /
           \   /
	     v
	    Mdb

Afterward, Mdb should work exactly as it did before, and is used the same in mdb-add.cpp. You’ll notice mdb-cat.cpp has been tweaked to use an MdbReader instead of Mdb, but otherwise remains unchanged from Part 1. You should now be able to use mdb-cat on read-only files, and it should report if a file doesn’t exist (instead of creating it).

Requirements

Hints

Example usage

(continuing from last example)
$ ./mdb-cat noexist_file
mdb-cat: noexist_file: fopen: No such file or directory
$ chmod -w mdb
$ ./mdb-cat mdb
   1: {new} said {msg}
   2: {cool} said {msg}
   3: {jae woo} said {mii}

Part 2b: Writing an mdb-grep program

Create a program mdb-grep which takes a pattern, an input database file path, and optionally an output database file path as arguments, performs a search on the input database for the RegEx pattern, and prints all matching records. If specified, these records should be written in the order they are found to the output database file.

Requirements

Hints

Example usage

(continuing from last example)
$ ./mdb-grep
usage: mdb-grep <pattern> <in_database_file> [out_database_file]
$ ./mdb-grep msg mdb
   1: {new} said {msg}
   2: {cool} said {msg}
$ ./mdb-grep '.*oo' mdb oowoo
   2: {cool} said {msg}
   3: {jae woo} said {mii}
$ ./mdb-grep '.*oo$' mdb
   3: {jae woo} said {mii}
$ ./mdb-grep '.*oo$' oowoo
   2: {jae woo} said {mii}
$ ./mdb-cat oowoo
   1: {cool} said {msg}
   2: {jae woo} said {mii}
$ # The following bash command shows that mdb-grep returns
$ # a non-zero exit code when there are no matching entries.
$ if ! ./mdb-grep noexist oowoo; then echo no match; fi
no match

Part 2c: Move it or lose it

Study the provided mdb-add-multi.cpp program. To make it work, you must implement move construction.

Requirements

Example usage

(continuing from last example)
$ chmod +w mdb
$ ./mdb-add-multi
database filename please (leave empty when done): mdb
database filename please (leave empty when done): mdb2
database filename please (leave empty when done): mdb3
database filename please (leave empty when done):
name please (will truncate to 15 chars): come in come in
msg please (will truncate to 23 chars): calling all mdbs
   4: {come in come in} said {calling all mdbs}
   1: {come in come in} said {calling all mdbs}
   1: {come in come in} said {calling all mdbs}
$ ./mdb-cat mdb mdb2 mdb3
   1: {new} said {msg}
   2: {cool} said {msg}
   3: {jae woo} said {mii}
   4: {come in come in} said {calling all mdbs}
   1: {come in come in} said {calling all mdbs}
   1: {come in come in} said {calling all mdbs}

Part 3: Using C++ file I/O

Work from the part3/ directory for this part.

Copy over your mdb.cpp and mdb.h from Part 2. Revise them to replace all instances of C file I/O (std::fopen, std::fread, std::fwrite, etc.) with C++’s std::ifstream and std::ofstream. All existing mdb-* utilities should work as they did before.

Requirements

Good luck!


Last updated: 2023-06-05