Sometimes you need a variable to hold several related chunks of data. In C, you can do this with a structure, commonly called a struct. Each chunk of data is known as a member of the struct.
For example, consider a program that computes a person’s Body Mass Index, or BMI. BMI is a person’s weight in kilograms divided by the square of the person’s height in meters. (BMI is a very imprecise tool for measuring a person’s fitness, but it makes a fine programming example.)
Create a new project: a C Command Line Tool named BMICalc. Edit main.c to declare a struct named Person that has two members: a float named heightInMeters and an int named weightInKilos. Then create two Person structs:
#include <stdio.h> // Here is the declaration of the struct struct Person { float heightInMeters; int weightInKilos; }; int main(int argc, const char * argv[]) { struct Person mikey; mikey.heightInMeters = 1.7; mikey.weightInKilos = 96; struct Person aaron; aaron.heightInMeters = 1.97; aaron.weightInKilos = 84; printf("mikey is %.2f meters talln", mikey.heightInMeters); printf("mikey weighs %d kilogramsn", mikey.weightInKilos); printf("aaron is %.2f meters talln", aaron.heightInMeters); printf("aaron weighs %d kilogramsn", aaron.weightInKilos); return 0; }
Notice that you access the members of a struct using a period (stylish programmers like to say “dot”). Build and run the program and confirm the output.
Here is the frame for main() after the struct’s members have been assigned values.
Most of the time, you use a struct declaration over and over again. So it is common to create a typedef for the struct type. A typedef defines an alias for a type declaration and allows you to use it more like the usual data types. Change main.c to create and use a typedef for struct Person. Notice that the code to replace is shown struck-through.
#include <stdio.h>// Here is the declaration of the structstruct Person { float heightInMeters; int weightInKilos; }; // Here is the declaration of the type Person typedef struct { float heightInMeters; int weightInKilos; } Person; int main(int argc, const char * argv[]) { struct Person mikey; Person mikey; mikey.heightInMeters = 1.7; mikey.weightInKilos = 96; struct Person aaron; Person aaron; aaron.heightInMeters = 1.97; aaron.weightInKilos = 84; printf("mikey is %.2f meters talln", mikey.heightInMeters); printf("mikey weighs %d kilogramsn", mikey.weightInKilos); printf("aaron is %.2f meters talln", aaron.heightInMeters); printf("aaron weighs %d kilogramsn", aaron.weightInKilos); return 0; }
You can pass a Person to another function. Add a function named bodyMassIndex() that accepts a Person as a parameter and calculates BMI. Then update main() to call this function:
#include <stdio.h> // Here is the declaration of the type Person typedef struct { float heightInMeters; int weightInKilos; } Person; float bodyMassIndex(Person p) { return p.weightInKilos / (p.heightInMeters * p.heightInMeters); } int main(int argc, const char * argv[]) { Person mikey; mikey.heightInMeters = 1.7; mikey.weightInKilos = 96; Person aaron; aaron.heightInMeters = 1.97; aaron.weightInKilos = 84; printf("mikey is %.2f meters talln", mikey.heightInMeters); printf("mikey weighs %d kilogramsn", mikey.weightInKilos); printf("aaron is %.2f meters talln", aaron.heightInMeters); printf("aaron weighs %d kilogramsn", aaron.weightInKilos); float bmi; bmi = bodyMassIndex(mikey); printf("mikey has a BMI of %.2fn", bmi); bmi = bodyMassIndex(aaron); printf("aaron has a BMI of %.2fn", bmi); return 0; }
Here you create a local variable bmi to hold the return value of bodyMassIndex(). You retrieve and print out the Mikey’s BMI. Then you reuse the variable to retrieve and print out Aaron’s BMI.
The first struct I had to deal with as a programmer was struct tm, which the standard C library uses to hold time broken down into its components. The struct is defined:
struct tm { int tm_sec; /* seconds after the minute [0-60] */ int tm_min; /* minutes after the hour [0-59] */ int tm_hour; /* hours since midnight [0-23] */ int tm_mday; /* day of the month [1-31] */ int tm_mon; /* months since January [0-11] */ int tm_year; /* years since 1900 */ int tm_wday; /* days since Sunday [0-6] */ int tm_yday; /* days since January 1 [0-365] */ int tm_isdst; /* Daylight Savings Time flag */ long tm_gmtoff; /* offset from CUT in seconds */ char *tm_zone; /* timezone abbreviation */ };
The function time() returns the number of seconds since the first moment of 1970 in Greenwich, England. localtime_r() can read that duration and pack a struct tm with the appropriate values. (It actually takes the address of the number of seconds since 1970 and the address of an struct tm.) Thus, getting the current time as a struct tm looks like this:
long secondsSince1970 = time(NULL); printf("It has been %ld seconds since 1970n", secondsSince1970); struct tm now; localtime_r(&secondsSince1970, &now); printf("The time is %d:%d:%dn", now.tm_hour, now.tm_min, now.tm_sec);
Your challenge is to write a program that will tell you what the date (4-30-2015 format is fine) will be in 4 million seconds.
(One hint: tm_mon = 0 means January, so be sure to add 1. Also, include the <time.h> header at the start of your program.)