C Tutorial (27) : Data Structures

Arrays and pointers are nice for lists of values, but those values must all be of the same data type. Sometimes you have different data types that must go together and be treated as a whole.

A perfect example is a customer record. For each customer, you have to track a name (character array), balance (double floating-point), address (character array), city (character array), state (character array), and zip code (character array or long integer). You would also want to access the customer record as a whole.

The C structure is the vehicle by which you group data such as would appear in a customer record and get to all the individual parts, called members. If you have many occurrences of that data and many customers, you need an array of structures.

Note : Other programming languages have equivalent data groupings called records/class. The designers of C wanted to call these data groupings structures, however, so that’s what they are in C.

Many times, a C structure holds data that you might store on 3×5 cards in a cardfile. Before personal computers, companies maintained a cardfile box with cards that contained a customer’s name, balance, address, city, state, and zip code, like the customer structure just described.

Defining a Structure

The first thing you must do is tell C exactly what your structure will look like. When you define variables of built-in data types such as an int, you don’t have to tell C what an int is—C already knows. When you want to define a structure, however, you must first tell C exactly what your structure looks like. Only then can you define variables for that structure.

Try to view a structure as just a group of individual data types. The entire structure has a name and can be considered a single value taken as a whole. You can access the individual members if you want to.

Only when you define a variable for the structure you describe does C give memory space to a structure variable.

To define an int variable, you only have to do this:

int i;

The struct statement defines the look (or layout) of a structure. Here is the format of struct:

struct [structure tag]
{
 member definition; 
 member definition;
 ...
 member definition;
};

The structure tag is a name you give to that particular structure’s look, but the structure tag has nothing to do with a structure variable name you might create later. After you define the format of a structure, you can define variables.

The member definitions are nothing more than regular built-in data type definitions such as int age;

Note : You can define a variable at the same time as the struct declaration statement, but most C programmers don’t do so. If you want to define a variable for the structure at the same time you declare the structure format itself, insert one or more variable names before the struct statement’s closing semicolon.

struct invStruct {
char manuf[25]; // Manufacturer name
char model[15]; // Model code
int diskSpace; // Disk size in Gigabytes 
int memSpace; // Memory Space in Gigabytes
int ports; // The number of USB ports on the system 
int quantity; // Number in inventory
float cost; // Cost of computer
float price; // Retail price of computer
};

c_structure_member

The previous structure definition does not define eight variables! The previous structure definition defines a single structure data type. The previous struct statement tells C what the user’s invStruct is supposed to look like. After C learns the structure’s format, C can define variables that take on the format of that structure when the user is ready to define variables.

If you create a structure that you might use again sometime, consider putting it in its own header file, or in a header file along with other common structures. Use #include to pull that header file into any source code that needs it.

struct invStruct item1, item2, item3;

Now you can put data into three variables. If you wanted to define 500 structure variables, you would use an array:

struct invStruct items[500];

 

struct invStruct {
char manuf[25]; // Manufacturer name 
char model[15]; // Model code
int diskSpace; // Disk size in Gigabytes 
int memSpace; // Memory Space in Gigabytes
int ports; // The number of USB ports on the system 
int quantity; // Number in inventory
float cost; // Cost of computer
float price; // Retail price of computer
};

main()
{
struct invStruct items[500];
// Rest of program would follow...

Perhaps you will need pointers to three structures instead of structure variables. Define them like this:

struct invStruct *item1, *item2,*item3; 
// Rest of program would follow

item1, item2, and item3 now can point to three structure variables. You can then reserve heap memory for the structures instead of using actual variables. (sizeof() works for structure variables to allow for heap structure data.) The following three statements reserve three heap structure areas and make item1, item2, and item3 point to those three heap values:

item1 = (struct invStruct *)malloc(sizeof(invStruct)); 
item2 = (struct invStruct *)malloc(sizeof(invStruct)); 
item3 = (struct invStruct *)malloc(sizeof(invStruct));

Putting Data in Structure Variables

A new operator, the dot operator, lets you put data in a structure variable’s individual members. Here is the format of the dot operator:

structureVariableName.memberName

To the left of the dot is always the name of a structure variable, such as item1 or employee[16]. To the right of the dot operator is always the name of a member from that structure, such as quantity, cost, or name. The dot operator puts data only in named structure variables. If you want to put data in a heap structure pointed to by a structure pointer variable, you must use the structure pointer operator, ->.

The first file is the header file containing the structure definition:

// Example program 
// File bookinfo.h
// This header file defines a structure for information about a book 

struct bookInfo {
char title[40]; 
char author[25]; 
float price; 
int pages;
};

And now the .c program file:

// Example program
// File Chapter27ex1.c
/* The program gets the bookInfo structure by including bookInfo.h 
   and asks the user to fill in three structures and then prints
   them. */
//First include the file with the structure definition 

#include "bookinfo.h"
#include <stdio.h>

main()
{
int ctr;
struct bookInfo books[3]; // Array of three structure variables

// Get the information about each book from the user
for (ctr = 0; ctr < 3; ctr++)
{
printf("What is the name of the book #%d?\n", (ctr+1)); 
gets(books[ctr].title);
puts("Who is the author? "); 
gets(books[ctr].author);
puts("How much did the book cost? "); 
scanf(" $%f", &books[ctr].price); 
puts("How many pages in the book? "); 
scanf(" %d", &books[ctr].pages);
getchar(); //Clears last newline for next loop
}

// Print a header line and then loop through and print the info
printf("\n\nHere is the collection of books: \n"); 
for (ctr = 0; ctr < 3; ctr++)
{
printf("#%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
printf("\nIt is %d pages and costs $%.2f", books[ctr].pages, books[ctr].price);
printf("\n\n");
}

return(0);
}

If you stored the structures on the heap, you couldn’t use the dot operator because the dot operator requires a variable name. Use -> to store data in heap structures. -> requires a pointer on the left and a member name on the right. Here is an equivalent program to the previous one.

/* The program again looks to fill three book structures with info, 
   but it uses a pointer array this time. */

//First include the file with the structure definition 

#include "bookinfo.h"
#include <stdio.h> 
#include <stdlib.h>

main()
{
int ctr;
struct bookInfo * books[3]; // Array of three structure variables

// Get the information about each book from the user
for (ctr = 0; ctr < 3; ctr++)
{
books[ctr] = (struct bookInfo*)malloc(sizeof (struct bookInfo));

printf("What is the name of the book #%d?\n", (ctr+1)); 
gets(books[ctr]->title);
puts("Who is the author? "); 
gets(books[ctr]->author);
puts("How much did the book cost? "); 
scanf(" $%f", &books[ctr]->price); 
puts("How many pages in the book? "); 
scanf(" %d", &books[ctr]->pages);

getchar(); //Clears newline input to keep things clean for 
// next round
}

// Print a header line and then loop through and print the info
printf("\n\nHere is the collection of books: \n"); 
for (ctr = 0; ctr < 3; ctr++)
{
printf("#%d: %s by %s", (ctr+1), books[ctr]->title, books[ctr]->author);
printf("\nIt is %d pages and costs $%.2f", books[ctr]->pages, books[ctr]->price);
printf("\n\n");
}

return(0);
}

 

Heap Memory < Prev                                                   Next > Disk Files (Sequential Access)

Advertisements

2 comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s