struct data type

struct data type

How to represent structured data?

A 3-dimensional vector:

#include <iostream>
using namespace std;

int main() {
  // a 3-d vector can be represented 
  // as an array with 3 elements:
  double vec[3] = {5.5, 15.1, -8.5};

  cout << "x = " << vec[0] << endl;
  cout << "y = " << vec[1] << endl;
  cout << "z = " << vec[2] << endl;
}

x = 5.5
y = 15.1
z = -8.5

The same 3-dimensional vector, but now using a user-defined structure (of three doubles named x, y, and z)

#include <iostream>
using namespace std;

struct Vec3d {
  double x;
  double y;
  double z;
};

int main() {
  
  Vec3d vec; // Declaring a structure vec of type Vec3d
  vec.x = 5.5;  vec.y = 15.1;  vec.z = -8.5;

  cout << "x = " << vec.x << endl;
  cout << "y = " << vec.y << endl;
  cout << "z = " << vec.z << endl;
}
x = 5.5
y = 15.1
z = -8.5

Structure members don’t have to be the same type

The example below shows a structure called Brush with two members, double radius and int color.

Also, observe how a structure can be initialized, the same way as the arrays:

#include <iostream>
using namespace std;

struct Brush {
  double radius;
  int color;
};

int main() {
  // initialize a brush with
  // radius = 5.5, and color = 1
  Brush b = { 5.5, 1 };

  cout << "radius = " << b.radius << endl; 
  
  cout << "color = " << b.color << endl; 
}
radius = 5.5
color = 1

Passing structures as function parameters, and returning them from a function.

In C++, by default, all function parameters are passed by value. And in this respect struct types not different from the simple types like int or double.

To make your function receive a structure variable passed by reference, we use the same function definition syntax, with the ampersand we used before:

Example: This program implements the functionality of a simple graphics editor, with a brush painting on the canvas.

We declare two structures:

The canvas is a 2-dimensional array of integers.

#include <iostream>
using namespace std;

const int W = 200;
const int H = 200;

struct Frame {
  int width;
  int height;
};

struct Brush {
  double radius;
  int color;
};

void show(int canvas[W][H], Frame fr) {
  for(int j = 0; j < fr.height; j++) {
    for (int i = 0; i < fr.width; i++) {
      if (canvas[i][j] == 0) 
        cout << '.';
      else
        cout << canvas[i][j];
    }
    cout << endl;
  }
  cout << endl;
}

void paint (int canvas[W][H], Frame fr, Brush br,
    int x, int y) 
{

  for(int j = 0; j < fr.height; j++) {
    for (int i = 0; i < fr.width; i++) {
      if ((x-i)*(x-i) + (y-j)*(y-j) <= 
          br.radius * br.radius)
      {
        canvas[i][j] = br.color;
      }
    }
  }

}

int main() {
  int canvas[W][H] = {0};
  Frame frame = {.width=30, .height=15};
  Brush brush = {5.5, 1};

  paint(canvas, frame, brush, 10, 8);

  brush.radius = 3.5;
  paint(canvas, frame, brush, 20, 9);
  
  brush.radius = 3.5; brush.color = 2;
  paint(canvas, frame, brush, 30, 2);
 
  brush.radius = 4.5; brush.color = 0;
  paint(canvas, frame, brush, 15, 7);

  show(canvas, frame);
}
............................22
...........................222
...........................222
........11111..............222
.......11111................22
......11111..................2
.....111111.........11........
.....111111.........111.......
.....111111.........1111......
.....111111.........1111......
.....1111111.......11111......
......1111111.....11111.......
.......1111111.....111........
........11111.................
..............................

We can return a structure type from a function

In this example, we define two functions make_bigger_brush and make_smaller_brush. Both of them accept a Brush structure as a parameter and return a new Brush structure with the same value of the member variable color, but a different value for its radius:

#include <iostream>
using namespace std;

struct Brush {
  double radius;
  int color;
};

// Create a bigger brush
Brush make_bigger_brush (Brush br) {
  
  // a new brush of x2 radius
  Brush br2;
  br2.radius = 2.0 * br.radius;
  br2.color = br.color;

  return br2;
}

// Create a smaller brush
Brush make_smaller_brush (Brush br) {
  
  // a new brush of x0.5 radius, copying the original one
  
  Brush br2 = br; // <-- you can copy the contents of the 
                  //     original brush variable 
                  //     in the new variable br2
                  
  br2.radius = 0.5 * br2.radius; // reduce its radius

  return br2;
}

int main () {
  Brush b1 = {5.0, 1};
  Brush b2 = make_bigger_brush(b1);
  Brush b3 = make_smaller_brush(b1);

  cout << "b1.radius = " << b1.radius << endl; 
  cout << "b1.color = "  << b1.color << endl << endl; 

  cout << "b2.radius = " << b2.radius << endl; 
  cout << "b2.color = "  << b2.color << endl << endl; 
  
  cout << "b3.radius = " << b3.radius << endl; 
  cout << "b3.color = "  << b3.color << endl << endl; 

  return 0;
}
b1.radius = 5
b1.color = 1

b2.radius = 10
b2.color = 1

b3.radius = 2.5
b3.color = 1

Nested structures

Nested structs are fine.

In the following example, we make a struct Canvas that contain the canvas array and the struct Frame. Notice that we pass this struct by reference to the function paint, because otherwise the array member data would not be updated by the function (if passed by value, the function would update a copy of the structure keeping the original structure unchanged).

#include <iostream>
using namespace std;

const int W = 200;
const int H = 200;

struct Frame {
  int width;
  int height;
};

struct Brush {
  double radius;
  int color;
};

struct Canvas {
  Frame frame;
  int data[W][H];
};

void show(Canvas & canvas) {
  for(int j = 0; j < canvas.frame.height; j++) {
    for (int i = 0; i < canvas.frame.width; i++) {
      if (canvas.data[i][j] == 0) 
        cout << '.';
      else
        cout << canvas.data[i][j];
    }
    cout << endl;
  }
  cout << endl;
}

void paint (Canvas & canvas, Brush br, int x, int y) 
{

  for(int j = 0; j < canvas.frame.height; j++) {
    for (int i = 0; i < canvas.frame.width; i++) {
      if ((x-i)*(x-i) + (y-j)*(y-j) <= 
          br.radius * br.radius)
      {
        canvas.data[i][j] = br.color;
      }
    }
  }

}

int main() {
  Canvas canvas = {{30, 15}, {0}};

  Brush brush = {5.5, 1};

  paint(canvas, brush, 10, 8);

  brush.radius = 3.5;
  paint(canvas, brush, 20, 9);
  
  brush.radius = 3.5; brush.color = 2;
  paint(canvas, brush, 30, 2);
 
  brush.radius = 4.5; brush.color = 0;
  paint(canvas, brush, 15, 7);

  show(canvas);
}
............................22
...........................222
...........................222
........11111..............222
.......11111................22
......11111..................2
.....111111.........11........
.....111111.........111.......
.....111111.........1111......
.....111111.........1111......
.....1111111.......11111......
......1111111.....11111.......
.......1111111.....111........
........11111.................
..............................