http://cpp.gantep.edu.tr
C++ resources. Faculty of Engineering, University of Gaziantep
 MAIN  -  Tutorials  -  Howtos  -  nmPrimer  -  Misc  -  Links  -  Contacts
C++ Tutorial (Advanced)
[index][<][1][2][3][4][5][6][>]

3. Data Structures

Last modified: Thu, 05 May 2011 09:54:58 +0300

Complete: ###################- (95%)

3.1 Introduction
3.2 Structures in C/C++
3.3 Structure Assignment
3.4 Using Structures with Functions
3.5 Using Structures with Vectors
3.6 Using Structures with Pointers
3.7 Examples
3.8 Exercises

3.1 Introduction

C++ allows you to define your own data types; these user-defined data types can be created using the struct keyword.

We have seen that an array (or vector) is a group of values (elements) all with the same name and data type. In contrast, a data structure is a group of values (members) all with the same object name but may differ in data type. The members each have different member names.

In this section we will see how to implement data structures using the struct keyword and how to use them with functions and vectors. In topic 4 the idea of data structures is taken further with C++ classes (the class keyword).

3.2 Structures in C/C++

A data structure (or derived data type) is a set of data elements grouped together under one name. These data elements, known as members, can have different types and different lengths.

A structure is declared using the struct keyword:

  struct name{
    type1 member_name1;
    type2 member_name2;
    .
    .
  } object_names;
For example, to collect the name and three exam scores of a student we can use the declaration:
  struct Student{
    string name;
    int mt1, mt2, fin;
    double  avr;
  } s1, s2;
Here, Student is a new valid type name like the fundamental ones int or double. s1 and s2 are objects (or variables) derived from this new type. You can also declare your objects as follows:
  struct Student{
    string name;
    int mt1, mt2, fin;
    double  avr;
  };

  Student s1, s2;
After declaring a new type, we can operate directly with their members. To do that we use a dot operator (.), placed between the object name and the member name.
  s1.name;
  s1.mt1;
  s1.mt2;
  s1.fin;
  s1.avr;

An example usage of the structures is given below.

03prg01.cpp: A basic use of the data structure
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
// A basic use of the data structure
#include <iostream>
#include <iomanip>
using namespace std;

struct Fruit{
  double weight;
  double price;
};

int main(){

  Fruit orange, apricot;

  // prices
  orange.price  = 2.50; // TL/kg
  apricot.price = 3.25; // TL/kg

  cout << "Input the amount of orange  in kg: "; cin >> orange.weight;
  cout << "Input the amount of apricot in kg: "; cin >> apricot.weight;

  cout << "\nTotal prices (TL):\n";
  cout << setprecision(2) << fixed;
  cout << "Orange  = " << orange.price * orange.weight << endl;
  cout << "Apricot = " << apricot.price * apricot.weight << endl;

  return 0;
}
Input the amount of orange  in kg: 2
Input the amount of apricot in kg: 1.5

Total prices (TL):
Orange  = 5.00
Apricot = 4.88

For detailed information, see also the Turkish-language web page: Yapılar ve Birlikler.

3.3 Structure Assignment

Assignment of values to data structures can be performed at declaration (i.e. initialisation):

  fruit apple  = {"UK",      0.411, 38};
  fruit banana = {"Ecuador", 0.512, 62};
Or after declaration, in this case we must reference the individual members.
  fruit apple, banana;

  apple.origin = "UK";
  apple.weight = 0.411;
  apple.price  = 38;

  banana.origin = "Ecuador";
  banana.weight = 0.512;
  banana.price  = 62;
Assignment can be performed directly from input:
  fruit kiwi;

  cin >> kiwi.origin;
  cin >> kiwi.price;
  cin >> kiwi.weight;

3.4 Using Structures with Functions

Variables (objects) defined with a struct can be passed to a function in the same way as for normal variables.

03prg02.cpp: Using Structures with Functions
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
// Using Structures with Functions
#include <iostream>
using namespace std;

struct fruit {
  string origin;
  double weight;
  int price;
};

void printProperties(fruit x) {
   cout << "Origin: " << x.origin << endl;
   cout << "Weight: " << x.weight << endl;
   cout << " Price: " << x.price  << endl;
}

int main() {
  fruit f = {"Asia", 2.45, 31};
  printProperties(f);
}
Origin: Asia
Weight: 2.45
 Price: 31

A function may return a struct value as in the example below.

03prg03.cpp: A function whose return value is a struct
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
// A function whose return value is a struct
#include <iostream>
using namespace std;

struct fruit {
  string origin;
  double weight;
  int price;
};

fruit setProperties(string s, double w, double p){
   fruit f;
   f.origin = s;
   f.weight = w;
   f.price  = p;
   return f;
}

int main(){
  fruit x = setProperties("Asia",2.45, 31);
  cout << x.origin << endl;
  cout << x.weight << endl;
  cout << x.price  << endl;
}
Asia
2.45
31

3.5 Using Structures with Vectors

Structures can be used with arrays and vectors. The following program illustrates a basic example usage of the fruit structure with vectors.

03prg04.cpp: Using data structures with vectors
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
// Using data structures with vectors
#include <iostream>
#include <vector>
using namespace std;

struct fruit {
  string origin;
  double weight;
  int price;
};

int main() {
  int n;
  cout << "How many fruits? ";
  cin >> n;

  // Define a vector whose elemements have type "fruit"
  vector<fruit> f(n);

  for(unsigned int i=0; i<f.size(); i++){
    cout << "Origin of fruit " << i+1 << "? "; cin >> f[i].origin;
    cout << "Price  of fruit " << i+1 << "? "; cin >> f[i].price;
    cout << "Weight of fruit " << i+1 << "? "; cin >> f[i].weight;
    cout << endl;
  }

  for(unsigned int i=0; i<f.size(); i++)
    cout << "Total price of fruit " << i+1 << " is "
         << f[i].weight * f[i].price << endl;
}
How many fruits? 2
Origin of fruit 1: Asia
Price  of fruit 1: 31
Weight of fruit 1: 1.5

Origin of fruit 2: Africa
Price  of fruit 2: 25
Weight of fruit 2: 2.6

Total price of fruit 1 is 4.5
Total price of fruit 2 is 5.2

Note that the counter in the for loop is unsigned as the result of f.size() is also unsigned. Using a signed counter will only result in a warning from the compiler.

The return value of a function can be a vector of a structure. In the following program the getList() function returns a vector (list) of fruits of given origin.

03prg05.cpp: A function returning a vector
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
 39:
 40:
 41:
 42:
 43:
 44:
 45:
 46:
 47:
 48:
 49:
 50:
 51:
 52:
 53:
 54:
 55:
// A function returning a vector
#include <iostream>
#include <iomanip>
#include <vector>
using namespace std;

struct fruit {
  string origin;
  double weight;
  int price;
};

vector<fruit> getList(vector<fruit>, string);

int main() {
  int n;
  cout << "How many fruits? ";
  cin >> n;

  // Define a vector whose elemements have type "fruit"
  vector<fruit> f(n);

  for(unsigned int i=0; i<f.size(); i++){
    cout << "Origin of fruit " << i+1 << "? "; cin >> f[i].origin;
    cout << "Price  of fruit " << i+1 << "? "; cin >> f[i].price;
    cout << "Weight of fruit " << i+1 << "? "; cin >> f[i].weight;
    cout << endl;
  }

  // Assign list of fruits from "Asia" to fa
  vector<fruit> fa = getList(f, "Asia");

  cout << "Fruits from Asia:\n";
  for(unsigned int i=0; i<fa.size(); i++){
    cout << fa[i].origin << "\t"
         << fa[i].weight << "\t" << fa[i].price << endl;
  }
}

// Returns a vector of fruits of given origin (source)
vector<fruit> getList(vector<fruit> f, string source){
  fruit x;
  vector<fruit> fr;

  for(unsigned int i=0; i<f.size(); i++){
    if(f[i].origin == source) {
        x.origin = f[i].origin;
        x.weight = f[i].weight;
        x.price  = f[i].weight;
        fr.push_back(x);
    }
  }
  return fr;
}
How many fruits? 5
Origin of fruit 1? Africa
Price  of fruit 1? 1
Weight of fruit 1? 1.5

Origin of fruit 2? Asia
Price  of fruit 2? 2
Weight of fruit 2? 2.2

Origin of fruit 3? Asia
Price  of fruit 3? 1
Weight of fruit 3? 5.5

Origin of fruit 4? Europe
Price  of fruit 4? 2
Weight of fruit 4? 3.4

Origin of fruit 5? Asia
Price  of fruit 5? 3
Weight of fruit 5? 4.3

Fruits from Asia:
Asia    2.2     2
Asia    5.5     5
Asia    4.3     4

3.6 Using Structures with Pointers

It is valid to create pointers that point to structures:

  fruit   f;
  fruit *pf;
Here f is an variable (object) of structure type fruit and pf is a a pointer to point to variables (objects) of structure type fruit. In this case, the following statement assigns the address of f to pf.
  pf = &f;
To access directly to members pointed by a pointer, we can use either the arrow operator (->)
  pf->price;
or use the statement
  (*pf).price;
Both notations have the same meaning.

Finally, in order to allocate memory dynamically at run-time we can use the new operator for structures.

  fruit *pf = new fruit;      // single element
  fruit *pf = new fruit[10];  // a block (array) of 10 elements

3.7 Examples

EXAMPLE 1: Element properties
Program 3.6 inputs element properties from the keyboard and stores them in a data structure. Here, atom is a variable that contains a list of element properties.

03prg06.cpp: Element properties
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
// Element properties
#include <iostream>
using namespace std;

struct elementProperties{
  int z;
  string name, clas;
  double mass;
};

int main () {

  elementProperties atom;

  cout << "Number: "; cin  >> atom.z;
  cout << "  Name: "; cin  >> atom.name;
  cout << " Class: "; cin  >> atom.clas;
  cout << "  Mass: "; cin  >> atom.mass;
}
Number: 3
  Name: Lithium
 Class: AlkaliMetal
  Mass: 6.941

To define an atom pointer, the program section within the main() program above can be written as follows:
  elementProperties *atom = new elementProperties;

  cout << "Number: "; cin  >> atom->z;
  cout << "  Name: "; cin  >> atom->name;
  cout << " Class: "; cin  >> atom->clas;
  cout << "  Mass: "; cin  >> atom->mass;
EXAMPLE 2: Concentration of orange juice
The figure given below shows a concentration of orange juice process using an evaporator system. In the concentration of orange juice, fresh juice containing s1(%) solids is fed to a vacuum evaporator at a rate of L (kg/hour). In the evaporator water is removed at a rate of W (kg/hour) and the solid content is increased to s2(%).


Fig 3.1: Concentration of orange juice

Analytical solution for L = 1000 kg/h, s1 = 7.08% and s2 = 58.0%.
Material balance : 1000 = W + C
Mass flow : 1000(7.08/100) = W(0) + C(58/100)

Solving these two equations gives:
C = 122.1 kg/h concentrated juice.
W = 877.9 kg/h water.

Program 3.7 calculates the outlet concentrated C (kg/hour) given values for L, s1 and s2.

03prg07.cpp: Concentration of orange juice
  1:
  2:
  3:
  4:
  5:
  6:
  7:
  8:
  9:
 10:
 11:
 12:
 13:
 14:
 15:
 16:
 17:
 18:
 19:
 20:
 21:
 22:
 23:
 24:
 25:
 26:
 27:
 28:
 29:
 30:
 31:
 32:
 33:
 34:
 35:
 36:
 37:
 38:
// Concentration of orange juice
#include <iostream>
using namespace std;

struct Evaporator {
  double imf, isc; // inlet  mass flow and concentration
  double omf, osc; // outlet mass flow and concentration
  double owf;      // outlet evaporated water flow
};

// Function returning evaporator solutions
Evaporator Solver(double L,    // inlet  mass flow
                  double s1,   // inlet  solid fraction
                  double s2) { // outlet solid fraction
  Evaporator x;
  x.imf = L;
  x.isc = s1/100;
  x.osc = s2/100;
  x.omf = L * (s1/100) / (s2/100);
  x.owf = L - x.omf;
  return x;
}

int main(){

  double imass, icon, ocon;
  cout << "Input initial mass flow (kg/h): ";
  cin  >> imass;
  cout << "Input initial concentration(%): ";
  cin  >> icon;
  cout << "Input desired concentration(%): ";
  cin  >> ocon;

  Evaporator j = Solver(imass, icon, ocon);

  cout << "Evaporated water flow   (kg/h): "<< j.owf <<endl;
  cout << "Final concentrated juice(kg/h): "<< j.omf <<endl;
}
Input initial mass flow (kg/h): 1000
Input initial concentration(%): 7.08
Input desired concentration(%): 58.0
Evaporated water flow   (kg/h): 877.931
Final concentrated juice(kg/h): 122.069

3.8 Exercises

  1. What is the action of the struct keyword in C/C++?
  2. Write a Point structure to represent a point whose Cartesian coordinates are x, y and z.
  3. Write a Car structure to represent a car whose members are color, model, age and license number.
  4. Write a University structure to represent a University whose members are city, number of students and number of departments.

5.   Market Database

(a) Implement a fruit data structure.
Each member of this structure will represent a fruit, storing its barcode, name, origin and price (in TL/kg).

(b) Consider that a file fruit.txt contains 13 different types of fruit.
The content of the file is given right.
The first column is a barcode, the second is the name, the third is origin and
the last column is the price (TL/kg).
Using the fruit structure in part (a), write a program to
i. read the data into a vector of type fruit,
ii. input the barcode and weight of a chosen fruit from the keyboard and
iii. output the properties and total price of the chosen fruit.
111 Apple         Africa   1.20
112 Apricot       Asia     3.25
113 Avocado       America  3.00
211 Banana        Asia     2.90
212 Blackberries  Europe   4.00
311 Cherries      Asia     3.15
411 Grapes        Europe   3.40
511 Kiwi          Asia     3.95
611 Melon         Asia     1.30
711 Orange        Africa   2.10
811 Plums         Europe   3.55
911 Strawberries  Europe   3.50
999 Walnuts       Asia     2.65

6.   Planets' Physical Characteristics.

Consider that a file nasa.txt contains data* for 9 planets in our solar system.
The first column is a name, the second is the mean radius (in km) and the third is equatorial gravity (in m/s2)
of the planet.

(a) Write a Planet structure to represent a planet whose properties are given above.

(b) Write a function whose prototype is
vector<Planet> lessGravity(vector<Planet> p);
to return a vector (list) of planets whose equatorial gravity less than Earth.
Use the function in a main program which reads the data into a vector of type Planet.

________________
* The data is extracted from NASA.

Mercury   2439.7   3.70
Venus     6051.8   8.87
Earth     6371.0   9.80
Mars      3389.5   3.71
Jupiter  69911.0  24.79
Saturn   58232.0  10.44
Uranus   25362.0   8.87
Neptune  24622.0  11.15
Pluto     1151.0   0.66

[index][<][1][2][3][4][5][6][>]
please send us you comments/questions/corrections