CSC 161 | Grinnell College | Spring, 2009 |
Imperative Problem Solving and Data Structures | ||
In this laboratory you will gain experience working with structs in the C programming language.
Functions, arrays, and parameters in C.
Consider the following struct that might be used in a campus directory:
#define MAX 20 struct entry { char first[MAX]; char last[MAX]; char dorm[MAX]; int phone; };
Write a function equalEntry that takes two entry records as parameters and returns true if the entries contain identical data and false otherwise.
Write a function comesFirst that takes two entry records as parameters and returns true if the name within the first entry comes before the name of the second. In comparing names, comesFirst initially should compare last names. If the last names are different, comesFirst should check dictionary order, ignorning capitalization. If the last names are identical, then comesFirst should compare the first names using dictionary order and ignoring capitalization.
Write a program that reads two entry records, prints whether they are identical (using equalEntry for the test), and prints which of the two entries comes first (using comesFirst).
Refer to the reading for this lab for a proposed definition of structure timeinto_t.
Structure types may be used as return types or argument types in functions. A function that converts time values given in seconds (e.g., 12345.67) to time values given in hh:mm:ss.sss format might have the prototype:
timeinfo_t convertTime( double realTime )
and would look like:
timeinfo_t convertTime( double realTime ) { timeinfo_t result; . . . return result; }
Complete the body of this function so that it converts real time values given as a number of seconds to hh:mm:ss.sss format.
Write a small test program that shows that 12345.67 seconds is equivalent to 3:25:45.67 (3 hours, 25 minutes and 45.67 seconds) by printing out the result.
A function for adding two times given in the hh:mm:ss.sss format might have the prototype
timeinfo_t addTimes( timeinfo_t one, timeinfo_t two )
Complete the addTimes
function so that it may be used to add
two times given in the hh:mm:ss.sss format.
Write a short test program that adds 1:2:3.33 to 2:3:4.44 and verify that you get 3:5:7.77.
If you wrote your addTimes
function using the "obvious"
algorithm, it will likely produce the result 10:63:12.33 when 5:30:12.33 is
added to 5:33:0.00. Note that the result has more than 59 minutes!
For this reason, it would be useful to have another function
that takes a single timeinfo_t
parameter, and returns a
"normalized" version of the parameter. That is, it returns a
result with the number of minutes and seconds both being between 0 and 59.
Write a function normalize
having prototype
timeinfo_t normalize( timeinfo_t originalTime )
that returns a normalized representation for originalTime
.
Then revise your addTimes
function so that it returns a
normalized time result.
Modify your test program so that it creates an un-normalized
timeinfo_t
variable (e.g., 10:63:12.33). Note that in C
there is no sense of a "private" member, so your main program can
initialize the members of a struct directly. For example,
timeinfo_t time1; time1.hours = 10; . . .
Then call your normalize
function, passing it the new struct.
Finally, check whether the original struct argument was changed by
normalize
.
Did you get the result that you expected? (The original should not have been changed, at least not unless you reassigned the return value of the function to the original struct variable.)
Passing and returning struct variables with the technique used above can be inefficient because the whole struct argument is copied to variables local to the function. It may be faster to pass and return pointers to struct variables.
Modify your addTimes
function from the previous exercise,
such that it now accepts the addresses of two
timeinfo_t
variables.
(Note that to accept the address of a struct, one must use a
parameter which is a pointer to the given struct type.) In addition, to
ensure that the function can not modify the original struct arguments
unintentionally, you should "const qualify" the parameters. Thus, your
function header should read as follows:
timeinfo_t addTimes( const timeinfo_t* one, const timeinfo_t* two )
Within your function, you can no longer access the members of each struct
with syntax such as one.hours
. Instead, you must use
one->hours
. Do you understand why?
Finally, be sure that when you call the function, you pass it addresses. For example,
timeinfo_t time3 = addTimes(&time1, &time2);
At this point, your program should work smoothly and produce the same results it did prior to this design upgrade.
This document is available on the World Wide Web as
http://www.walker.cs.grinnell.edu/courses/161.sp09/lab-structs.shtml
Part A: | created 11 April 2008 by Henry M. Walker revised 11 April 2008 |
![]() ![]() |
Parts B, C: | created and revised 2001-2004 at the University of Toronto
by Alan Rosenthal and Tom Fairgrieve revised March 2007 by Marge Coahran with permission from Alan and Tom | |
Full Lab: | revised 11 April 2008 by Henry M. Walker last revised 25 January 2009 by Henry M. Walker | |
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu. |