Project 4: Pointers and Dynamic Memory

1. Introduction and set up

The goal of this project is for you to practice using pointers and dynamic memory.

In this project you will implement a map. Recall that a map (also called a dictionary or associative array) associates keys with values. The most familiar example is Java's HashMap. See the Map in Java's API as an example of the functionality.

This map will be implemented using a linked list, so the code we saw at the beginning of class on Friday (Oct 12) will be a handy comparison. Resist the temptation to refer to your code as a hash map. The "hash" in "hashmap" refers to a specific way to implement a map (or set). We are not doing hashing in this lab. But we will learn about hashing later in the semester.

Your map will associate strings with strings (that is, both the keys and values will be strings), so this will also give you a little practice working with strings in C (although we will be doing no real processing on strings). The driver program makes a map from countries to capitals.

Copy the given code.

mkdir proj4
cd proj4
cp ~tvandrun/Public/cs245/proj4/* .

2. Inspecting the code

First look at the driver program (driver.c) to get a handle on what your map needs to do. The first part of the file contains a big static array with the raw data we are going to use. You can largely skip over that---direct your attention to the main() function.

(If you look at the list of countries, you'll notice some entries like Northern Ireland, Puerto Rico, Transnistria, and Palestine, which for various reasons (status, independence, recognition, etc) raise the question of how we define country. I simply grabbed this list from Wikipedia's list of national capitals, which you can check out yourself if you're interested in the political status of any of the nations included. No political message is intended on my part by including or excluding any entity.)

Notice in the main() function we have a map pointer m which we initialize to the result of create(), which allocates an empty map. We have a loop to populate the map. Then we exercise the functions containsKey() and put().

Then we iterate through all the associations in the map. Recall that with Java's HashMap this is done by getting the keyset from the hash map, an iterator from the keyset, and using the keys (gotten from the keyset) to obtain the value for each key, like this:

     for (Iterator it = map.keySet().iterator(); it.hasNext(); ) {
            String key = it.next();
            System.out.println(key + " " + map.get(key));
    }

Lacking both a good "set" type and iterators in C, what we do here is define a function numKeys() which allocates and returns an array containing all the keys. Notice that the result is stored in a variable keySet that has type char**, which is essentially "array of strings." (Remember that strings are really just character arrays, and arrays are just pointers. So char** is interpreted as "pointer to (array of) pointer(s) to (array of) char(s)." Make sure you understand that. Ask for help if you don't.

Finally we call destroy() which shall deallocate everything in the map.

Now you need to master map.h. The structs for nodes and the map are already written for you but you must understand them completely. Notice that the nodes do not have a single datum but two data: a key and a value.

Then look at the functions in map.c. create() and numKeys() are written for you as examples. I also have provided a functiongetNode(), which is not listed in map.h. It is for convenience---the analogue of a private helper method in Java.

3. Your tasks

In the following specific tasks for you to do, remember that anything you allocate (or that is allocated in the code you're given) must have an identifiable deallocation somewhere in the code. However, notice that all the strings themselves are allocated statically. You never need to copy the contents of these strings---just store and refer to them using pointers. You do not need to deallocate them--in fact, you must not. free() won't like it if you try to deallocate something that is statically allocated.

A. put()

Given a pointer to a map, add the association given by the parameters. (What if there already is an association for the given key?) This will likely involve allocating a new node; by the end of the project, you should be able to account for when it is deallocated.

B. get()

Retrieve the value, given a key.

C. rem()

Remove a key (and its value) from the map. Don't forget to clean up and deallocate the node---but don't deallocate the contents of the node. Also, remove should return the value associated with the indicated key (which is now being removed), if any (NULL otherwise). (See the remove() method in Java's HashMap class.)

D. containsKey()

Test to see if a given key exists in the map.

E. keys()

Here's the hard one. You need to allocate an appropriate-lengthed array of strings (that is, an array for holding character pointers). Then you need to populate it. (Where is this deallocated? Look in the driver.)

F. destroy()

Clean up and deallocate all the nodes and the map itself (but not the strings).

4. Turn-in

Please put all the files you modified in a directory and submit that directory using the "handin" command:

/cslab/class/csci245/bin/handin project5 (name of your directory or files)

DUE: Monday, Oct 28, at 5:00 pm.


Thomas VanDrunen
Last modified: Thu Oct 31 12:45:12 CDT 2013