KAIST
EE 209: Programming Structures for EE

Assignment 3: Customer Management Table Assignment

 

Purpose

The purpose of this assignment is to help you learn how to implement common data structures in C and how to exploit them to achieve modularity in a real-world application. It also will give you the opportunity to gain more experience with the GNU/Linux programming tools, especially bash, emacs, and gdb.

Background

A data structure is a way of organizing data for efficient operation. In this assignment, you will implement the required functionalities (register, unregister, and find) of a customer management program using the following data structures.

Your Task

You will implement and improve the customer data management API using various data structures. Your tasks in this assignment are below:

The customer_manager Interface

customer_manager is an API library for the customer data management, where the users can register the customer information and perform lookup operations to retrieve the purchase amount information.

The customer_manager interface introduces a structure type definition, DB_T:

The customer_manager interface is described in a file named customer_manager.h, and it contains these function declarations:

DB_T CreateCustomerDB(void);
void DestroyCustomerDB(DB_T d);
int RegisterCustomer(DB_T d, const char *id, const char *name, const int purchase);
int UnregisterCustomerByID(DB_T d, const char *id);
int UnregisterCustomerByName(DB_T d, const char *name);
int GetPurchaseByID(DB_T d, const char *id);
int GetPurchaseByName(DB_T d, const char *name);
typedef int (*FUNCPTR_T)(const char* id, const char* name, const int purchase);
int GetSumCustomerPurchase(DB_T d, FUNCPTR_T fp);

customer_manager.h

What each function does is as follows:

[Task 1] The customer_manager Array Implementation

The goal of the first task is to implement the customer_manager API using a dynamically resizable array. Array is the simplest data structure that works well for a small number of user items.

Your first customer_manager implementation should be as follows:

customer_manager1.c

Implementation tips:
You must implement dynamically resizable array. You will not get a full credit if you do not implement array expansion.

[Task 2] The customer_manager Hash Table Implementation

Unfortunately, using an array is slow when you deal with a large number of user items. Frequent reqistration and unregisteration of a user item creates many holes (empty elements) scattered across the array, which, in turn, makes these operations slow. Adding, deleting, and searching of a user item would eventually depend on linear search (unless you take extra measures to manage the holes separately).

We improve the performance of customer_manager operations with a hash table in this task. Actually, you would need two hash tables. One is for looking up a user item with ID as a key, and the other is for a lookup with a name as a key.

Your hash table-based customer_manager implementation should:

Implementation tips: The following figure represents an example hash table-based customer_manager implementation (it uses the hash_function mentioned above). hash function overview

[Task 3] Testing Your Library and Measuring the Performance

We provide testclient.c to test your implementations. It first checks the correctness of your library functions and measures the performance over various user items. Note that we may use other programs for grading.

testclient.c

To compile your code, do the following:

// test your array-based implementation
$ gcc209 -o testclient1 testclient.c customer_manager1.c
$ ./testclient1

// test your hash table-based implementation
$ gcc209 -o testclient2 testclient.c customer_manager2.c
$ ./testclient2

(Extra credit: 15% ) We will give an extra credit to the students whose implementation is the fastest among all students. Note that only assignments whose basic functionality is implemented without problems deserve the extra credit. We may use our own program to measure the performance.

Rank # Extra credit
1 15%
2-3 10%
4-6 5%
7-10 3%

Logistics

Develop in your own environment using emacs to create source code and gdb to debug. Make sure to compile with gcc209 and test your code on lab machine before submission.

Please follow the steps through Task 1 to Task 3 to complete the customer_manager API, and test your libraries.

We give two opportunities for getting an extra credit (each 15%).

Create a readme text file that contains:

Submission

Use KAIST KLMS to submit your assignments. Your submission should be one gzipped tar file whose name is YourStudentID_assign3.tar.gz

For example, if your student ID is 20191234, please name the file as 20191234_assign3.tar.gz

Create a local directory named 'YourStudentID_assign3' and place all your files in it. Then, tar your submission file. Please refer here for how to archive your assignment.

Your submission need to include the following files:

Your submission file should look like this:

20191234_assign3.tar.gz
customer_manager.h
customer_manager1.c
customer_manager2.c
readme
EthicsOath.pdf
  • You can use this checker before you submit.
  • Do not add files which has not been mentioned above.
    Do not put another source files in your submission. Your implementation must lay in customer_manager.h, customer_manager1.c and customer_manager2.c, not in other files.
    (You MUST not modify customer_manager.h)
    The name of the files must be exact. Note that file name is case sensitive. You might not get the full credit if the names are not correct.

    Late Submission

    You can use the late submission (late pass; as known as a token) which can be late up to three days without penalty for the first four programming assignments. That is, you can apply your late submission days (within 3 days in total) spread over the first four programming assignments. The minimum granulaity is one day: if you are 1 hour late, that's still counted as one day late. If you're going to spend your free late days, please say so in your readme file.

    You need to notify your token usage in your readme file in following format; [TOKEN=n] where n is the number of tokens that you want to use. For example, if you want to use 2 tokens, following text MUST be included in your readme.

    [TOKEN=2]

    You need to strictly follow this format. Otherwise, TAs will not consider your late token usage.

    Grading

    If your code cannot be compiled at eelab5 with gcc209, we cannot give you any points (0 point). Please double check before you submit.
    Please note that you might not get a full credit even if you pass the test with your testclient. TAs might use another testclient to test functionality and robustness of your implementation.

    We will grade your work on quality from the user's point of view and from the programmer's point of view. To encourage good coding practices, we will deduct points if gcc209 generates warning messages.

    From the user's point of view, your module has quality if it behaves as it should.

    In part, style is defined by the rules given in The Practice of Programming (Kernighan and Pike), as summarized by the Rules of Programming Style document. These additional rules apply:

    Names: You should use a clear and consistent style for variable and function names. One example of such a style is to prefix each variable name with characters that indicate its type. For example, the prefix c might indicate that the variable is of type char, i might indicate int, pc might mean char*, ui might mean unsigned int, etc. But it is fine to use another style -- a style which does not include the type of a variable in its name -- as long as the result is a readable program.

    Line lengths: Limit line lengths in your source code to 72 characters. Doing so allows us to print your work in two columns, thus saving paper.

    Comments: Each source code file should begin with a comment that includes your name, the number of the assignment, and the name of the file.

    Comments: Each function should begin with a comment that describes what the function does from the caller's point of view. The function comment should:

    Comments: Each structure type definition and each structure field definition should have a comment that describes it.

    Comments should be written in English.

    FAQ

    Question 1

    Can I use assert macro in my submission source code?

    Answer

    You can use assert for your debugging. However, your code MUST still be able to return NULL to the caller without your assert code.

    It is highly recommended to test if your code compiles without the assert macro (use -DNDEBUG flag when compile). We will use -DNDEBUG option with gcc209 for compiling and grading. Make sure to check your source code before submission. If your code does not compile with -DNDEBUG, you will not get full credit and may get huge deduction in grading.

    Question 2

    In Part 1, do I need to shrink the pArray back when unregistering customers?

    Answer

    You don't need to shrink pArray.

    Question 3

    When implementing RegisterCustomer, should we consider the case where name or id is blank string (e.g, ‘’) as error and return -1?

    Answer

    No, name or id can be a blank string. Therefore, you should consider it as normal case(not error case).

    Question 4

    If the unregistering functions cause free item space in the array, should we fill the free space?

    Answer

    It's up to you handle the free space. As long as it register/unregister function works fine, it won’t be a problem.

    Question 5

    For the following code,

    struct UserInfo {
        char *name;
    };
    
    struct UserInfo *p;
    p = (struct UserInfo *) calloc(1, sizeof(struct UserInfo));
    p->name = strdup("Kevin");

    In order to free all the allocated memory, is it fine just to free(p) or do I need to free(p->name) as well?

    Answer

    You need to free all the allocated memory including p->name for this case, or else there will be memory leak.

    Question 6

    In the hash table expansion of the task 2, it states that we need to expand "when the number of nodes in a hash table reaches 75% of the number of buckets". What does it mean?

    Answer

    It means that you need to expand when total number of User item in hash table reaches 75 % of the number of buckets.