CS31 Lab 1: C Warm-up: Employee Database

Due before 11:59pm, Wednesday, Sept. 11

This lab should be done with your assigned lab partner: Lab 1 partners

Lab 1 Goals:

Lab 1 Starting Point Code

First, both you and your partner should run update31 to grab the starting point code for this assignment.

  $ update31
  $ cd cs31/labs/01
  $ pwd
  /home/your_user_name/cs31/labs/01
  $ ls
  Makefile  employeedb.txt  readfile.c  readfile.h  small.txt  workersDB.c
The starting point code includes:
  1. Makefile: a makefile you should use to compile your program
  2. small.txt, employee.txt: two example input files to your program (small.txt is the one you should use to do most of your testing as you incrementally implement and test parts of your solution)
  3. readfile.h, readfile.c: DO NOT CHANGE ANY CODE IN THESE FILES. This is a file reading C library. You can make calls to functions in this library in your program. The workersDB.c file has an example of how to use this library to read in values from an input DB files listed as a command line option.
  4. workersDB.c: the starting point file into which you will add your C solution. The starting point code includes two functions:
    • get_filename_from_commandline: takes a string and the command line arguments and initializes the string to the filename command line argument. You should not change this function, but feel free to change where it is called in your final program.
    • read_and_print_file: an example debug function showing an example of how to use the readfile library functions to read information from the input file into program variables. Your final program should not call this function. Use it as an example of how to read values from the file.
    The rest of the lab 1, Employee DB functionality, should be added to this file, as should good comments.

To compile and run (and use make to compile, otherwise you need to compile and link in the readfile library by hand, which you don't want to do):

     make
     ./workersDB small.txt

Here are a few suggestions for ways to share code with your partner.

Lab 1 Introduction

Employee Database Program

For this lab, you will implement an employee database program in C. Your program will store employee information in an array of employee structs, sorted by employee ID value. Employee information will be read in from an input file when your program first starts-up.

Your program should print out a menu of transaction options, read in the user's next option, and performs the chosen operation on the employee database. The options your program must support are the following (Do not change the numbering of these menu options in your program (i.e. menu option 2 must be look up by ID, option 5 must be quit, ... ):

  1. Print the Database
  2. Lookup by ID
  3. Lookup by last name
  4. Add an Employee
  5. Quit
Your program continues handling the user's transaction choices until the user enters 5, the "QUIT" option.

Project Details and Requirements

Program Start-up

Your program will take one command line argument, which is the name of the input file containing employee information. There is no guarantee that the input file is in sorted order, so you program must ensure that the resulting array of employee information is sorted by employee ID. Here is an example command line:
./workerDB small.txt        
The code to get the file name string is provided for you in the starting point code.

File Format

The input file format consists of several lines of an ascii file. Each line contains the information for one employee in the following order:
six_digit_ID  first_name  last_name  salary  
For example, here is a file with 4 employees:
998447 Nik Nayak 63000 
473836 Renuka Ladlow 93000
493570 Christopher Yie 70000 
518364 Yewande Jones 85000
With the starting point code are two sample employee data base files you can use to test your code.

With the starting point code is a readfile library that contains functions you can use to read values from the file. See the "File I/O" section below for more details.

Employee Struct

You should define an employee struct with fields to store information for one employee. Think about which types you want to use for the different fields, and use meaningful field names. Because the DB supports a look-up operation by last name, I suggest storing first and last name values in two separate fields rather than in a single name field. You may assume that no first nor last name is longer than 64 characters, including the trailing '\0' character.

Here is an example of how I might define a Person struct to store a single name and age value for each person:

#define MAXNAME  64     // define and use constants for values that don't change

struct personT {
   char name[MAXNAME];   // a C-style string (array of chars)
   int  age;             
};
Also, look at some of the weekly lab code examples for how to define and use struct types


Valid Field Values: Use the following information about valid field values to help you decide which type to use for individual fields (for some fields there may be more than one reasonable choice):

File I/O

For this assignment you will use functions in the provided readfile library (in the files readfile.c and readfile.h). You should not change any code in these files. The readfile.h file contains function prototypes for the readfile library. There are function comments in this file that describe each function and a high-level comment describes how to use the library. Also, look at the read_and_print_file function in workersDB.c for an example of how to use these functions.

Here are the general rules for how to use these functions:

  1. open a file by calling: open_file, passing in the name of the file to open as a string (open_file returns 0 if the file is successfully opened, and -1 if the file cannot be opened).

  2. make calls to read values of different types into program variables: read_int, read_string, read_float. These functions take arguments much like scanf does: they need to know the memory location of where to put the value read in. For example:
    int x;
    float f;
    char s[20];
    ...
    // these functions return 0 on success or -1 if read fails or
    // if there is nothing left to read (end-of-file has been reached).
    ret = read_float(&f); // returns 0 on success, -1 on EOF 
    ret = read_int(&x)    // returns 0 on success, -1 on EOF
    ret = read_string(s)  // returns 0 on success, -1 on EOF
    

  3. close the file when you are done with it: close_file

If you are curious, the implementation of these functions is in readfile.c. You can take a look and see how it uses the C FILE * interface and fscanf functions for reading. We will use this interface directly later in the semester.

User Input

Reading in input from the user, like menu options, should be done using scanf. See my C documentation and weekly lab code for examples of scanf.

Array of Employee Data

The Employee data read in from the file should be stored in an array of Employee structs, in sorted order by increasing ID value. You may use any sorting algorithm you'd like to sort the array. You may assume that there are never more than 1024 employees.

Program Main Loop

Once your program has read in the data base and initialized the sorted array, it should enter a loop that prints out the menu of transaction options, reads in the user's next option, and performs the requested action. Some actions may require further input from the user. Your program should ensure at each step that the user enters valid values (e.g. no negative menu options), and re-prompts the user to enter until s/he enters valid values. You do not need to handle all types of bad user input (and in fact you cannot using scanf). For example, if the user enters a string when an int was expected, you have no way right now to handle that. You may find your program gets into an infinite loop in a case like this. If so, remember that CNTRL-C will kill it.

The following are details about each menu option you must support.

Print the Database

You should print the contents of the database in tabular format followed by printing out the total number of employees in the database. See the sample output for an example. Your output does not need to be identical to mine, but it should have a similar tabular form. Look at my printf documentation for examples.

Lookup by ID

Prompt the user to enter an employee ID value and use BINARY SEARCH to find a matching employee in the data base. If one is found, print out the Employee information. If not, print out a "not found" message to the user.

Lookup by Last Name

Prompt the user to enter a last name and search the array to find a matching employee in the data base. If one is found, print out the Employee information. If not, print out a "not found" message to the user. If there is more than one employee with a matching last name, just return information for one just one of the matches (you do not need to find all matches, just one).

Add an Employee

Your program should prompt the user to enter the information for each field in the employee struct. It should also ensure that the user enters valid values for each field, and print out an error message and re-prompt the user to try again, repeating until the user enters valid values. It should then print out the field values of the employee to add, and ask the user if s/he really wants to add the employee. If yes, insert the new employee in the array. Remember that you must maintain correct sorted order. Inserting a new employee in the middle of the array, requires "making a hole for it" by shifting values over. For example, if the array currently has 5 employees and the new employee should go in bucket 2, you need to shift the current employee data in buckets 2-4 over one to make a "hole" in bucket 2 for the new employee. Inserting one new Employee should require at most an O(n) algorithm (don't implement anything less efficient than that). The post conditions of a successful add are the db size increases by one, and the array is still sorted.

Quit

When the user chooses quit, you should exit the main loop and print out some kind of goodbye message before your program exit.

Requirements and Hints

This is a fairly large programming assignment, similar to something you may have done near the end of CS21. Use all you know about top-down design and incremental implementation and testing to help you implement a good modular and bug-free solution.
Example Output
Here is output from a run of a working program. It does not show every menu option, nor all possible error handling, but should give you some idea of what a correct program may look like. Your program's output does not need to be identical to mine, but it should include meaningful prompts to the user and should print out the result of the transaction in an easy to read way.

Extra Challenge
After completing a well-designed, well-commented, correct solution to the required parts of this assignment, as an extra challenge try adding some or all of the following menu option(s), and add them after the QUIT option (DO NOT change the numeric values for the five required options):

The remove option should prompt the user to enter an employee ID number, search for that employee in the DB and if found ask the user if s/he really wants to remove. If so, the employee record should be removed from the array. Make sure to leave no holes in the array (i.e. if there are 10 employees, their info should be in array buckets 0-9).

The update option can be used to change any field of an employee. Your program should prompt the user to enter an employee ID to first find the matching employee whose data you want to change. The user should have the option of changing any or all fields.

For the print highest salaries option your program should prompt the user to enter a value for M (e.g. 5), and then print out the employee information for the M (5) employees with the highest salary. Your solution should require only one pass through the employee DB. And, remember it is important that the Employee database remain sorted by employee ID after this menu option are chosen.

For the find all with last name, return information about every employee with a matching last name.

Here is some sample output of some of a solution with a couple of the extra features added (remove and print with highest salaries). NOTE the ordering of the required features and the extra features menu options.

Submit

Once you are satisfied with your solution, first type 'make clean' to remove all executable files from your labs/01 directory and then hand in you solution by typing handin31 at the unix prompt.

Only one of you or your partner should run handin31 to submit your joint solutions If you accidentally both run it, send me email right away letting me know which of the two solutions I should keep and which I should discard (you don't want the grader to just guess and grade the wrong one).

You may run handin31 as many times as you like, and only the most recent submission will be recorded. This is useful if you realize, after handing in some programs, that you'd like to make a few more changes to them.