C++ language is equipped with several basic data types such as `int`

, `double`

, `bool`

,
`char`

, `long int`

, `long double`

, etc.
The C++-standard library adds also other commonly used data types like `std::string`

to represent text and
`std::vector`

to represent sequences of values.

Programmers can also define new data types to represent entities such as a point in a $2$D space or a rectangle. Let’s first see why programmers may want to define their own data types.

## Why to define new data types?

Assume that one is writing a program that deals with rectangles and operations with rectangles such as to draw rectangles. For each rectangle, there is the following information associated to it, as illustrated in the figure below.

To define a rectangle one needs a point and the rectangle’s color. A point in a $2$D space is represented by two integer coordinates. The color is represented using the RGB-color model which requires three integers (between $0$ and $255$) to represent red, green, and blue.

A function to draw a rectangle can be declared as follows (function’s implementation is less important now).

```
void draw_rectangle(int x, int y, int h, int b, int a, int r, int g, int bl);
```

And, a call to the function follows.

```
draw_rectangle(2, 2, 4, 8, 45, 255, 153, 102);
```

Functions with many arguments, like `draw_rectangle`

, are difficult to understand.
These functions also induce easily in error when calling them because one needs to recall exactly what each argument, from a rather long list, represents.
Obviously, it’s easy to mix up the arguments.
One way to tackle the problem is to define a new type to represent rectangles which contains all the data described above (i.e. a point, the height, the base, etc).

```
// A new type to represent rectangles
struct Rectangle {
// A point
// Height
// Base
// An angle
// A color
};
```

Then, the function `draw_rectangle`

can be declared as follows.

```
void draw_rectangle(const Rectangle& r);
```

One can then define variables of type `Rectangle`

and call the function `draw_rectangle`

.

```
Rectangle my_rectangle = // initialize the rectangle;
draw_reactangle(my_rectangle);
```

Note that function `draw_rectangle`

has now one argument, instead of height “anonymous” arguments.
This latter version requires a lower cognitive burden and recall effort from the programmers to be able to use the function correctly.

**Good programming practice:** keep the number of function arguments low.

Defining new data types also makes programs more readable and self-explanatory.

Next, we introduce how new data types can be defined with `struct`

and give examples.
In the section Example, we then return to an example using the `Rectangle`

data type.

## The basics: struct

A `struct`

defines a new type consisting of a sequence of members.
For instance, the `struct`

below defines a point in a $2$D space as two integer members, one representing the $x$-coordinate and
the other representing the $y$-coordinate.

```
struct Point {
int x = 0; // the x-coordinate
int y = 0; // the y-coordinate
};
```

It’s then possible to define variables of type `Point`

and initialize them.

```
Point origin;
Point p1 = {4, 8};
```

The first point, `origin`

, has its `x`

and `y`

members initialized automatically with zero,
while `p1`

’s `x`

and `y`

members are initialized with $4$ and $8$, respectively.

It’s also possible to modify the `x`

and `y`

coordinates of point `p1`

.

```
p1.x = -1;
p1.y = 10;
```

Note that variable `p1`

consists of two integers placed in the memory one after the other.
Thus, if an integer occupies four bytes, then `p1`

consists of eight consecutive bytes,
where the first four bytes are associated with `p1.x`

and the next
four bytes are associated with `p1.y`

.
The figure below illustrates this idea.

It’s possible that a `struct`

occupies more memory bytes than the sum of its members’ memory due to memory alignment issues (also know as *padding*).
For simplicity, we ignore this aspect in this tutorial.

It’s also possible to define a vector of points. The example below shows a vector initialized with three points: $(5,5)$, $(0,1)$, and $(-2,6)$.

```
std::vector<Point> points_list = {{5,5}}, {0,1}, {-2,6}};
```

We can also define

- a function that reads two user given coordinates and returns a point; and
- a function to display a point.

```
Point read_point() {
std::cout << "Enter point coordinates: ";
Point p;
std::cin >> p.x >> p.y;
return p;
}
void display_point(const Point& p) {
std::cout << "(" << p.x << ", " << p.y << ")";
}
```

As you can see, functions can return a `struct`

(e.g. a `Point`

) and a `struct`

can also be a function argument
(like in function `display_point`

).
Note that call by `const`

reference is used to pass a `Point`

to function `display_point`

.
Firstly, we want to avoid copying a `struct`

which has several members.
Secondly, the function should not modify the variable (of type `Point`

) passed to it.

It’s also possible to assign a `Point`

variable to another `Point`

variable.

```
Point origin;
Point p1 = {4, 8};
p1 = origin; // copy origin's coordinates to p1's coordinates
//p1.x = origin.x;
//p1.y = orogin.y;
```

In this way, all members of `origin`

are copied into the corresponding members of `p1`

.

Comparing variables of type `Point`

with the operators `<, <=, >, >=, ==, !=`

is not possible.

```
if (p1 < origin) { // compilation error!!
// do something
}
if (p1 == origin) { // compilation error!!
// do something
}
```

What would the meaning of `p1 < origin`

be? What are we comparing? The `x`

-coordinates? The `y`

-coordinates?
The distance of the points to point $(0,0)$?
If the programmer needs to compare points then she must define a boolean function that defines the meaning of the comparison.
For instance, one can define a function `less_than`

to compare two points based
on their distance to point $(0,0)$. First, a function that returns the distance between two points is defined.
This function is then called by function `less_than`

.

```
#include <cmath> // sqrt, pow
double distance(const Point& p1, const Point& p2) {
return (std::sqrt(std::pow(p1.x - p2.x, 2) + std::pow(p1.y - p2.y, 2)));
}
// Return true if distance of p1 to point(0,0) is less than distance of p2 to (0,0)
bool less_than(const Point& p1, const Point& p2) {
Point origin = {0,0};
return distance(p1, origin) < distance(p2, origin);
}
```

Recall that the math functions `std::pow`

and `std::sqrt`

are defined in the C++-standard library `cmath`

.

We can use function `less_than`

to sort increasingly a list of points stored in a vector
by their distance to point $(0,0)$.

```
void swap(Point& p1, Point& p2){
Point aux = p1;
p1 = p2;
p2 = aux;
}
// Bubble sort algorithm
void sort(std::vector<Point>& V) {
for (int pass = 1; pass < V.size(); ++pass) {
for (int i = 0; i < V.size() - 1; ++i) {
if ( less_than(V[i + 1], V[i]) ) { // wrong order?
swap(V[i], V[i + 1]);
}
}
}
}
```

## Example

We return now to our initial problem about rectangles. You can find below a program that reads a list of user given rectangles and stores it in a vector. It then loops through the list and displays the each of the rectangles.

First, two new types are defined, `Point`

and `RGB`

, to represent a point in $2$D-space and a RGB color, respectively.
These types are then used to define the type `Rectangle`

.

```
struct Point {
int x = 0;
int y = 0;
};
struct RGB {
int red = 0;
int green = 0;
int blue = 0;
};
struct Rectangle {
Point lower_left_corner;
int height = 0;
int base = 0;
int angle = 0;
RGB color;
};
Rectangle r = {{2, 3}, 3, 4, 45, {209, 102, 131}};
```

The figure below depicts the rectangle `r`

members in the computer’s memory.
Assume that each slot in the figure stores an `int`

(i.e. $4$ bytes).

The program below reads a list of rectangles given by the user and stores the list in a vector. The user marks the end of the input list by giving a rectangle with a height or base less than or equal to zero. The program then draws all rectangles in the list.

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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104

#include <iostream>
#include <vector>
struct Point {
int x = 0;
int y = 0;
};
struct RGB {
int red = 0;
int green = 0;
int blue = 0;
};
struct Rectangle {
Point lower_left_corner;
int height = 0;
int base = 0;
int angle = 0;
RGB color;
};
Point read_point();
RGB read_color();
Rectangle read_rectangle();
// Read a list of user given rectangles
// Stop reading when height <= 0 or base <= 0
// Return a vector with the rectangles read
std::vector<Rectangle> read_reactangle_list();
void draw_rectangle(const Rectangle& r);
/* ****************** */
int main() {
// Create a list of rectangles
std::vector<Rectangle> rectangles_list = read_reactangle_list();
std::cout << "\n";
std::cout << "\n";
for (Rectangle r : rectangles_list) {
draw_rectangle(r);
}
}
/* ****************** */
Point read_point() {
std::cout << "Enter point coordinates:\n";
Point p;
std::cin >> p.x >> p.y;
return p;
}
RGB read_color() {
RGB c;
std::cout << "Enter a color (RGB values):\n";
std::cin >> c.red >> c.green >> c.blue;
return c;
}
Rectangle read_rectangle() {
Rectangle r;
r.lower_left_corner = read_point();
std::cout << "Enter height and base:\n";
std::cin >> r.height >> r.base;
std::cout << "Enter angle:\n";
std::cin >> r.angle;
r.color = read_color();
return r;
}
// Read a list of user given rectangles
// Stop reading when height <= 0 or base <= 0
// Return a vector with the rectangles read
std::vector<Rectangle> read_reactangle_list() {
std::vector<Rectangle> V;
for (Rectangle r = read_rectangle(); r.height > 0 && r.base > 0; r = read_rectangle()) {
V.push_back(r);
}
return V;
}
void draw_rectangle(const Rectangle& r) {
// Code to draw rectangle r goes here
std::cout << "Drawing a rectangle with area " << r.height * r.base << "\n"; // just for testing
}

Though the code above compiles and executes, we skip here the implementation of function `draw_rectangle`

because
it would require the use of graphic libraries which are outside the scope of the course.
Some libraries that could be used are, for instance

- Fast Light Toolkit (FLTK)
- Windows GDI
- OpenGL

You can use *Coliru* and modify the program above to display the RGB color codes and area of each rectangle entered by the user.
Write first a function that displays the RGB color and aread of a given rectangle.
This function should then be called in the `main`

, for each rectangle stored in the vector `rectangles_list`

.