This lab should be done with your assigned lab partner:
Lab 1 partners
Lab 1 Goals:
- Practice with C programming basics: declaring vars, type, arrays, functions
- Writing C code and functions that uses statically declared
arrays and structs and arrays of structs.
- Practice writing and using C functions. Pass by value: basic types
and array parameters.
- C I/O: scanf, printf, and using a file reading library.
- More practice with top-down design.
- Using a Makefile.
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:
- Makefile: a makefile you should use to compile your program
- 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)
- 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.
- 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, ...
):
- Print the Database
- Lookup by ID
- Lookup by last name
- Add an Employee
- 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):
- The six digit ID value must be between 100000 and 999999 inclusive.
- Salary amounts must be between $30,000 and $150,000 inclusive.
- The salary is a positive whole number amount (no decimals).
- You can assume that every employee has exactly two names
(a first and a last), so you cannot hire Cher nor Jennifer Love Hewitt.
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:
- 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).
- 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
- 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.
- Make use of my C programming resources and links and refer to example C
code I've given you in class and lab.
- Your code should be well-designed, modular, robust, use meaningful
variable and function names, and must be well-commented. This
includes having a top-level comment describing your program and listing
your and your partner's names and the date. In addition, every function
should be well-commented. Read and follow my
C Style Guide. This document describes what I expect for good
function and program comments and has some tips for how to avoid line
wrapping. Some of this documentation refers to parts of C that you have
not yet learned.
- Before even starting to write code, use top-down design
to break your
program into manageable functionality.
- Your solution should have at least 6 function-worthy functions
in addition to main.
- Use incremental implementation and testing, and use function stubs
to help test program control flow.
Here is one suggestion for getting started:
- add the employee struct definition
- add some debug code to main declaring an employee struct and
accessing some of its fields to ensure that it is defined correctly.
- implement the function(s) to read in and initialize the array of
employee structs and call it from main. You can ignore sorting it
for now if you'd like.
- implement the print DB option next. This will help you with debugging
the other menu options.
- then implement and test individual menu option functionality one at
a time. Add in sorting the array by employee ID before the look-up by
ID and the add an employee options.
- Your program should test for invalid input values entered by the user
(like invalid menu options). Your program does not need to handle the user
entering incorrect type data (like a string instead of an int value).
- Your program should take a single command line argument, the employee
DB file. The starting point code includes code to convert the command line
argument to a string with the filename and to handle badly formed command
lines.
- Your program should not use global variables. You should use only
local variables and parameters. So, if a function needs a
value from the caller, then that value should be passed in as a parameter.
If a function needs some variables to compute what it needs to compute,
then those should be declared as local variables inside the function.
If you don't know what a global variable is, that is great, you won't
make the mistake of using one.
- Make use of constants (#defines) for values that do not change in your
program
- You may assume that all names (first or last) are less than 64 characters long
- You may assume that no employee database has more that 1024 employees.
- Make use of my C programming resources and code that I gave you in class
and in lab to help you figure out C syntax.
- Use tabular format when printing out the employee database.
- Use debug printfs to help you see what your program is doing, but
make sure to remove all debug output from your submitted code.
- Make sure to test boundary cases for different options. For example,
does your "add employee" work for adding at the beginning, middle, and
end of the array?
- Use CNTRL-C to kill a running program stuck in an infinite
loop.
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):
- Remove an Employee
- update an employee's information
- print the M employees with the highest salaries
- find all with last name
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.