Section 3.5
Structures
cplusplus.com

Data structures.

A data structure is a set of diverse types of data that may have different lengths grouped together under a unique declaration. Its form is the following:
struct model_name {
  type1 element1;
  type2 element2;
  type3 element3;
  .
  .
} object_name;
where model_name is a name for the model of the structure type and the optional parameter object_name is a valid identifier (or identifiers) for structure object instantiations. Within curly brackets { } they are the types and their sub-identifiers corresponding to the elements that compose the structure.

If the structure definition includes the parameter model_name (optional), that parameter becomes a valid type name equivalent to the structure. For example:

struct products {
  char name [30];
  float price;
} ;

products apple;
products orange, melon;
We have first defined the structure model products with two fields: name and price, each of a different type. We have then used the name of the structure type (products) to declare three objects of that type: apple, orange and melon.

Once declared, products has become a new valid type name like the fundamental ones int, char or short and we are able to declare objects (variables) of that type.

The optional field object_name that can go at the end of the structure declaration serves to directly declare objects of the structure type. For example, we can also declare the structure objects apple, orange and melon this way:

struct products {
  char name [30];
  float price;
} apple, orange, melon;
Moreover, in cases like the last one in which we took advantage of the declaration of the structure model to declare objects of it, the parameter model_name (in this case products) becomes optional. Although if model_name is not included it will not be possible to declare more objects of this same model later.

It is important to clearly differentiate between what is a structure model, and what is a structure object. Using the terms we used with variables, the model is the type, and the object is the variable. We can instantiate many objects (variables) from a single model (type).

Once we have declared our three objects of a determined structure model (apple, orange and melon) we can operate with the fields that form them. To do that we have to use a point (.) inserted between the object name and the field name. For example, we could operate with any of these elements as if they were standard variables of their respective types:

apple.name
apple.price
orange.name
orange.price
melon.name
melon.price
each one being of its corresponding data type: apple.name, orange.name and melon.name are of type char[30], and apple.price, orange.price and melon.price are of type float.

We are going to leave apples, oranges and melons and go with an example about movies:

// example about structures
#include <iostream.h>
#include <string.h>
#include <stdlib.h>

struct movies_t {
  char title [50];
  int year;
} mine, yours;

void printmovie (movies_t movie);

int main ()
{
  char buffer [50];

  strcpy (mine.title, "2001 A Space Odyssey");
  mine.year = 1968;

  cout << "Enter title: ";
  cin.getline (yours.title,50);
  cout << "Enter year: ";
  cin.getline (buffer,50);
  yours.year = atoi (buffer);

  cout << "My favourite movie is:\n ";
  printmovie (mine);
  cout << "And yours:\n ";
  printmovie (yours);
  return 0;
}

void printmovie (movies_t movie)
{
  cout << movie.title;
  cout << " (" << movie.year << ")\n";
}

Enter title: Alien
Enter year: 1979
 
My favourite movie is:
 2001 A Space Odyssey (1968)
And yours:
 Alien (1979)

The example shows how we can use the elements of a structure and the structure itself as normal variables. For example, yours.year is a valid variable of type int, and mine.title is a valid array of 50 chars.

Notice that mine and yours are also treated as valid variables of type movies_t when being passed to the function printmovie(). Therefore, one of the most important advantages of structures is that we can refer either to their elements individually or to the entire structure as a block.

Structures are a feature used very often to build data bases, specially if we consider the possibility of building arrays of them.

// array of structures
#include <iostream.h>
#include <stdlib.h>

#define N_MOVIES 5

struct movies_t {
  char title [50];
  int year;
} films [N_MOVIES];

void printmovie (movies_t movie);

int main ()
{
  char buffer [50];
  int n;
  for (n=0; n<N_MOVIES; n++)
  {
    cout << "Enter title: ";
    cin.getline (films[n].title,50);
    cout << "Enter year: ";
    cin.getline (buffer,50);
    films[n].year = atoi (buffer);
  }
  cout << "\nYou have entered these movies:\n";
  for (n=0; n<N_MOVIES; n++)
    printmovie (films[n]);
  return 0;
}

void printmovie (movies_t movie)
{
  cout << movie.title;
  cout << " (" << movie.year << ")\n";
}

Enter title: Alien
Enter year: 1979
Enter title: Blade Runner
Enter year: 1982
Enter title: Matrix
Enter year: 1999
Enter title: Rear Window
Enter year: 1954
Enter title: Taxi Driver
Enter year: 1975
 
You have entered these movies:
Alien (1979)
Blade Runner (1982)
Matrix (1999)
Rear Window (1954)
Taxi Driver (1975)

Pointers to structures

Like any other type, structures can be pointed by pointers. The rules are the same as for any fundamental data type: The pointer must be declared as a pointer to the structure:
struct movies_t {
  char title [50];
  int year;
};

movies_t amovie;
movies_t * pmovie;
Here amovie is an object of struct type movies_t and pmovie is a pointer to point to objects of struct type movies_t. So, the following, as with fundamental types, would also be valid:
pmovie = &amovie;
Ok, we will now go with another example, that will serve to introduce a new operator:

// pointers to structures
#include <iostream.h>
#include <stdlib.h>

struct movies_t {
  char title [50];
  int year;
};


int main ()
{
  char buffer[50];

  movies_t amovie;
  movies_t * pmovie;
  pmovie = & amovie;

  cout << "Enter title: ";
  cin.getline (pmovie->title,50);
  cout << "Enter year: ";
  cin.getline (buffer,50);
  pmovie->year = atoi (buffer);

  cout << "\nYou have entered:\n";
  cout << pmovie->title;
  cout << " (" << pmovie->year << ")\n";

  return 0;
}


Enter title: Matrix
Enter year: 1999
 
You have entered:
Matrix (1999)

The previous code includes an important introduction: operator ->. This is a reference operator that is used exclusively with pointers to structures and pointers to classes. It allows us not to have to use parenthesis on each reference to a structure member. In the example we used:

pmovie->title
that could be translated to:
(*pmovie).title
both expressions pmovie->title and (*pmovie).title are valid and mean that we are evaluating the element title of the structure pointed by pmovie. You must distinguish it clearly from:
*pmovie.title
that is equivalent to
*(pmovie.title)
and that would serve to evaluate the value pointed by element title of structure movies, that in this case (where title is not a pointer) it would not make much sense. The following panel summarizes possible combinations of pointers and structures:
Expression DescriptionEquivalent
pmovie.title Element title of structure pmovie 
pmovie->title Element title of structure pointed by pmovie(*pmovie).title
*pmovie.title Value pointed by element title of structure pmovie*(pmovie.title)

Nesting structures

Structures can also be nested so that a valid element of a structure can also be another structure.
struct movies_t {
  char title [50];
  int year;
}

struct friends_t {
  char name [50];
  char email [50];
  movies_t favourite_movie;
  } charlie, maria;

friends_t * pfriends = &charlie;
Therefore, after the previous declaration we could use the following expressions:
charlie.name
maria.favourite_movie.title
charlie.favourite_movie.year
pfriends->favourite_movie.year
(where, by the way, the last two expressions are equivalent).

The concept of structures that has been discussed in this section is the same as used in C language, nevertheless, in C++, the structure concept has been extended up to the same functionality of a class with the peculiarity that all of its elements are considered public. But you will have more details about this topic on section 4.1, Classes.

© The C++ Resources Network, 2000-2003 - All rights reserved

Previous:
3-4. Dynamic memory

index
Next:
3-6. User defined data types.