CSC 161 Grinnell College Spring, 2009 Imperative Problem Solving and Data Structures

Structures in C — structs

Goals

In this laboratory you will gain experience working with structs in the C programming language.

Prerequisites:

Functions, arrays, and parameters in C.

Steps for this Lab

Part A: Getting Started

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;
};
```
1. Write a function equalEntry that takes two entry records as parameters and returns true if the entries contain identical data and false otherwise.

2. 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.

3. 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).

Part B 2: Representing Time with a Struct

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;
}
```
1. 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.

2. 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.

1. 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.

Part C: Passing Structs to Functions

1. 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.)

2. 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);
```

```     http://www.walker.cs.grinnell.edu/courses/161.sp09/lab-structs.shtml