April 17 '01

In this class, we discussed

Why are structures necessary

One of the important requirements of a programming language is the ability to represent real world objects in a convenient manner. Datatypes are a result of this need. Some datatypes are so simple and are encountered frequently, and so the types are built into the language. These are the predefined types - such as int, float, char etc.
However, as the objects to be represented become complex, the predefined types are no longer sufficient. At this point, it becomes necessary to allow the programmer to define new types, which are called user-defined types.
Many objects are really the aggregate of smaller pieces. Eg. a date is an aggregation of a day, a month and a year. A credit card is an aggregate of a number, a name, an expiration date, a balance and a limit. Each individual credit card may have different values for these smaller parts ( called fields ), but all credit cards must have these pieces of information.
These aggregates are usually referred to as structures, and form one of the bases of object oriented programming.

Using structures in C

To represent structures in C, two things need to done. First, the type must be defined, and then variables of that type must be declared.

Defining structures in C

Structures are defined in the top-level in a file i.e. outside of all functions.
To define a new type, start with the keyword struct, then give a name for the type, then an opening brace {. Declare each of the fields which make up the type, exactly as you would declare variables. Finally, use a closing brace } and a semicolon ;.
#include < stdio.h >

/* Define a new type to reperesent days of the year */
struct Date {
    int day;
    int month;
    int year;
};  /* Do not forget the semicolon */

/* Define a new type to represent a CreditCard */
struct CreditCard {
    int number;
    char name[40];
    float balance;
    float limit;
};

int main()
{
    /* Do not define new types here */
    /* However, variables of the new types must be declared here */
    struct Date birthday;  /* Declare birthday to be of type struct
                              Date */
    struct Date holiday;   /* Declare holiday to be of type struct
                              Date */

    struct CreditCard chaseCard, citiCard;  /* Declare chaseCard and
                                               citiCard to be of type
                                               struct CreditCard */

    /* Do something here */

    return 0;
}

Accessing fields

Structures are accessed using the individual fields. In the previous example, to set the birthday of a person to May 12 1970, the following code would be written after /* Do something here */
    birthday.day = 12;
    birthday.month = 5;
    birthday.year = 1970;
Note how the left hand side is formed by combining the name of the variable (birthday) a dot . and the fields that were declared in the type definition of struct Date.
Not all the fields need to be set at the same time, but you should set the value of a field before you use it.
In the above example, we have set the fields of birthday. It is important to note that this does not affect holiday in any way i.e. holiday.day is undefined.
Fields can be used in expressions. eg.
    holiday.day = birthday.day + 5;
    holiday.month = 7;
    holiday.year = 2000 + holiday.month + birthday.day;
    /* These expressions do not make sense, but they do illustrate how
    fields can be used in expressions */

Using fields in arrays and functions

Like variables of any other datatype, one can declare arrays of structure types, and can pass variables of structure types to functions.
#include < stdio.h >
struct Date {
    int day;
    int month;
    int year;
};

int getDaysFromYearStart(struct Date today)
{
    int days;

    days = day;  /* incorrect !!  day has no meaning on its own. */
    days = today.day;
    days += 30 * (today.month - 1);  /* Keep it simple now */
    
    if (today.year % 4 == 0  && today.month > 2)
        days += 1;
    return days;
}


int main()
{
    struct Date birthday;
    struct Date holidays[20];
    int i;

    printf("Please enter the date in dd/mm/yy: ");
    scanf("%d/%d/%d", & birthday.day, & birthday.month,
                      & birthday.year);

    printf("Days since beginning of the year is %d\n",
       getDaysFromYearStart(birthday) );  /* pass the entire sturcture
                                             as a parameter */
    for (i=0; i<20; i++)
    {
        printf("Enter a holiday : ");
        scanf("%d/%d/%d", & holidays[i].day, & holidays[i].month,
                          & holidays[i].year );
        printf("Days since beginning of the year is %d\n",
           getDaysFromYearStart(holidays[i]) );
    }
    return 0;
}