กก

Section 3.5
Structures
cplusplus.com

Data structures.

A data structure is a set of diverse types of data with different lengths grouped 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 objects. Within key brackets { } they are the types and their names corresponding to the elements that compose the structure.

If the structure definition includes the parameter model_name, 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, of different types. 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 became a new valid type name like the fundamental ones int, char or short. And since then we have been 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, to declare the structure objects apple, orange and melon like we have done previously we could also have done it this way:

struct products {
  char name [30];
  float price;
} apple, orange, melon;
Moreover, in cases like this last one in which we took advantage of the declaration of the structure model to declare objects of the same one, 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 more ahead.

Once we have declared our three objects from a structure (apple, orange and melon) we can operate with the fields that compose them. For that we have to use a point (.) inserted between the object name and the field name. For example, we could operate with anyone 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);

main ()
{
  char buffer [50];

  strcpy (mine.title, "Star wars");
  mine.year = 1978;

  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: Matrix
Enter year: 1999
 
My favourite movie is:
 Star wars (1978)
And yours:
 Matrix (1999)

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

Notice that either mine and yours are also treated as valid variables of type movie_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 all the structure as a block.

Structures are a very used resource to build data bases, specially if we consider the possibility to build 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);

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: Favourite movie 1
Enter year: 1991
Enter title: Favourite movie 2
Enter year: 1992
Enter title: Favourite movie 3
Enter year: 1993
Enter title: Favourite movie 4
Enter year: 1994
Enter title: Favourite movie 5
Enter year: 1995
 
You have entered these movies:
Favourite movie 1 (1991)
Favourite movie 2 (1992)
Favourite movie 3 (1993)
Favourite movie 4 (1994)
Favourite movie 5 (1995)

Pointers to structures

Like any other type, structures can be pointed by pointers. The rules are the same than for fundamental data types: The pointer must be declared as 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, will also be valid:
pmovie = &amovie;
Ok, now we will go with another example, that will serve us 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 incorporates a new important operator, the operator ->. This one is a reference operator that is used exclusively with pointers to structures and pointers to classes. This allows us not to have to use parenthesis on each reference. In the example we used:

movies->title
that could be translated to:
(*movies).title
both expressions movies->title and (*movies).title are valid and mean that we are evaluating the element title of the structure pointed by movies. You must distinguish it clearly from:
*movies.title
that is equivalent to
*(movies.title)
and that would serve to evaluate the value pointed by element title of structure movies, that in this case would not have much sense. The following panel summarizes possible combinations of pointers and structures:
Expression DescriptionEquivalent
movies.title Element title of structure movies 
movies->title Element title of structure pointed by movies(*movies).title
*movies.title Value pointed by element title of structure movies*(movies.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;
Thus, 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 way how structures have been used in this section is the one that it is used with C language's structures, nevertheless, in C++ the structure concept has been extended until the same functionality of a class with the peculiarity that all of its elements are considered public. But you will have more details on this topic in section 4.1, Classes.

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

Previous:
3-4. Dynamic memory

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