In CS 125, 225, and other classes, you have used various languages that are considered to be "C based", but up to now you may have very limited experience in C programming. This MP will provide a short programming introduction to pointers, strings, and functions in C.
This machine problem will be divided up into two pieces. In the first piece, you will need to write some code to call some 'creatively defined' functions so that those functions produce the desired output. In the second piece, you will be creating a simple dictionary data structure to parse and hold the values of the parsed strings.
We have pre-uploaded some files to your mp1 svn directory, including mp1-functions.c. Inside mp1-functions.c, you will see ten different functions, including first_step() (re-printed below).
void first_step(int value)
{
if (value == 81)
printf("1: Illinois\n");
}
To complete Part 1, you must complete the program part1.c so that part1.c makes calls to all ten functions in mp1-functions.c such that they print their "Illinois" line. When running ./part1, your output should look exactly like:
1: Illinois
2: Illinois
3: Illinois
4: Illinois
5: Illinois
6: Illinois
7: Illinois
8: Illinois
9: Illinois
10: Illinois
You should NOT edit the mp1-functions.c file. In fact, when we grade your program, we will replace the mp1-functions.c file with a new version of the file (and we'll change the "Illinois" string so printing out "Illinois" in a for-loop will get you no credit).
Now that you have some review of pointers, we're ready to make a simple, but useful library. This library will be a simple "dictionary" that associates a key with value, much like the Map interface in Java (Interface Map<K, V> in Java). While a true library may contain many useful functions, we only require a few very basic functions to be completed in order to complete Part 2: _init(), _destroy(), _add(), _get(), _remove(), and _parse().
In all six functions, the first parameter is a pointer to a dictionary_t struct. You can find this struct defined in the libdictionary.h file inside the /libdictionary/ folder in MP1. You will find the dictionary_t structure, with a single reference to a dictionary_entry_t struct. You may want to add variables to dictionary_t, change it to a pointer, or anything else to work with your data structure. It may be useful to add variables inside the dictionary_entry_t struct in order to store state about your dictionary. You may find that the dictionary_entry_t struct is enough, or you may create any number of other structs inside your .h file. A pointer to the same dictionary_t will be used through the entire use of a single dictionary. Sample code of use of your library can be found in part2.c, re-printed (in part) below:
dictionary_t dictionary;
dictionary_init(&dictionary);
result = dictionary_add(&dictionary, "key", "value");
result = dictionary_add(&dictionary, "key2", "value");
result = dictionary_parse(&dictionary, "Hello: World");
[...]
dictionary_remove(&dictionary, "key3");
You should modify part2.c to include more robust testing your library. We will not use part2.c in grading, but our grader will use a custom file that makes use of your library -- it's up to you to robustly test your dictionary.
To complete Part 2, you must implement the six functions defined in libdictionary/libdictionary.c. These functions are self-descriptive, but a full function outline is provided for you below for each function. In this MP, we are looking for correctness over efficiency -- all the test cases are small enough that even an O(n^3) algorithm will run just fine.
void dictionary_init(dictionary_t *d)
Initialize your dictionary data structure d. If your data structure does not require any initialization logic, this function may be empty.
Parameters:int dictionary_add(dictionary_t *d, const char *key, const char *value)
Adds the key-value pair (key, value) to the dictionary d, if and only if the dictionary does not already contain a key with the same name as key. This function should NOT make a copy of the Key and value.
Parameters:int dictionary_parse(dictionary_t *d, char *key_value)
Parses the key_value string and add the parsed key and value to the dictionary. This function must make a call to dictionary_add() when adding to the dictionary. The format of the key_value will be the format of an HTTP header (you can read more aboud the headers here, but this is not necessary to understand), where the contents will be the KEY (one or more non-colon characters), a colon, a single space, and the rest will be the VALUE. (While the KEY cannot be an empty string, it is possible for the VALUE to be an empty string.)
This function should NOT copy key_value and should NOT create any additional memory to store the KEY and VALUE pieces of the string. Instead, this function should modify the key_value string in-place, if necessary.
Valid Inputs:const char *dictionary_get(dictionary_t *d, const char *key)
Returns the value of the key-value element with the key name key from the dictionary d. If the key does not exist, this function should return NULL.
Parameters:int dictionary_remove(dictionary_t *d, const char *key)
Removes the element with the key key from the dictionary d, if d contains the key.
Parameters:void dictionary_destroy(dictionary_t *d)
Frees any memory associated with the dictionary d.
Parameters:make cleanTo run Part 1:
make
./part1To run Part 2:
./part2