Integrating Structures with Arrays, Functions and Pointers
Learn about using structures in structured programming constructs like arrays, functions, and pointers.
Nested structures
A structure defined inside another structure is called a nested structure. It allows us to organize related data and set a hierarchy in the code format, reducing the complexity of the code and making it easier to understand.
Defining structures inside other structures
To define a nested structure, we can declare the whole structure (Example 1) or a structure variable (Example 2) inside another structure.
#include<iostream>#include<string>using namespace std;struct Person{string name;struct Date {int day;int month;int year;} dob;};
Example 1: We declare a structure named Date
and its structure variable (dob
) inside a second structure called Person
.
Example 2: We declare the structures Date
and Person
separately. We only declare a structure variable of the structure Date
called dob
inside the Person
structure.
Accessing members of nested structures
To access the member of a nested structure, we use the .
(dot) operator for which we follow this general syntax: outer_struct.inner_struct.member
. A working example to portray this concept is given below.
#include <iostream>using namespace std;struct Date{int day;int month;int year;};struct Person{string name;Date dob;};int main(){Person p = {"John", {30, 5, 1999}};cout << "Name: " << p.name << endl;cout << "DOB: " << p.dob.day << "/" << p.dob.month << "/" << p.dob.year << endl;return 0;}
Lines 4–9: The
Date
structure is declared, having threeint
type variables:day
,month
, andyear
.Lines 11–15: The
Person
structure is declared, having astring
typename
variable and adob
structure variable.Line 19: A
p
structure variable of thePerson
structure is declared and initialized, also initializing thedob
structure variable of theDate
structure inside the curly brackets separated by the comma.Line 20: The
string
typename
variable is printed by using a single.
operator functionality.Line 21: The
dob
structure variable is printed using the double.
operator functionality for each member.
An array of structures
Technically speaking, the structure is nothing but a data type. So, like any other data type, we can form an array
of structures. Let’s look at how we can create and access an array
of the Student
structure with two members, name
and age
, defined below.
struct Student{string name;int age;};
Defining an array of structures
A declaration of an array
of the Student
structure will have the following syntax:
Student students[3]{{"John", 23},{"Jane", 18},{"Alice", 25}};
A pictorial version of this concept will look like this:
Accessing individual members of the array
Just like a standard array, to access individual members of an array of structures, we need to access each array element using the index operator. A working example is given below.
#include <iostream>using namespace std;struct Student{string name;int age;};int main(){//DeclarationStudent students[3];//Separate initializationstudents[0] = {"John", 23};students[1] = {"Jane", 18};students[2] = {"Alice", 25};//Accessing membersfor (int i = 0; i < 3; i++){cout << "Name: " << students[i].name << endl;cout << "Age: " << students[i].age << endl;}return 0;}
Lines 4–8: The
Student
structure is declared.Line 13: An
array
of data typeStudent
of length3
is declared.Lines 15–17: Array elements are initialized at each index.
Lines 19–23: A
for
loop is used to iterate over thestudents
array to access every individual member using the.
(dot) operator.
Passing structures to functions
We can also pass structures to functions. Instead of passing multiple variables, we can send one structure with all these variables as its members. This is probably one of the most helpful functionality structures given to us while writing large codes, making the variable and code management much better. Here’s an example:
#include <iostream>using namespace std;struct Rectangle{int length;int width;};double area(Rectangle r){return r.length * r.width;}int main(){Rectangle r = {2, 5};cout << "Area of Rectangle: " << area(r) << endl;return 0;}
Lines 4–8: A structure named
Rectangle
is declared withlength
andwidth
as its members.Line 10: The
area
function is declared, and ther
structure variable of theRectangle
structure is given as its parameter.Line 12: The
area
of the rectangle is calculated by taking the product of the members of the structure variable and is returned.Line 17: An
r
structure variable is declared and initialized.Line 18: The result of the product (
area
) is printed.
Using structs to return multiple values
Furthermore, with the utilization of structures, there is no longer a need to pass variables by reference in order to update multiple values using a function (which is restricted in C++ when it comes to returning multiple values). Instead, we can simply return the structure itself. Let’s see an example.
#include <iostream>using namespace std;struct Point2D{double x;double y;};Point2D midpoint(Point2D p1, Point2D p2){Point2D m;m.x = (p1.x + p2.x) / 2.0;m.y = (p1.y + p2.y) / 2.0;return m;}int main(){Point2D p1= {0.0,0.0};Point2D p2= {1.0,1.0};Point2D m = midpoint(p1, p2);cout << "Mid point: ("<<m.x<<","<<m.y<<")"<<endl;return 0;}
Lines 4–8: A structure named
Point2D
is declared with coordinatesx
andy
as its members.Line 10: A
midpoint
function of the typePoint2D
is declared, which takes twoPoint2D
variables to compute their midpoint. It’s important for the function to have the same return type as thePoint2D
structure because we have to return a structure variable.Lines 12: An
m
structure variable is declared, which stores the midpoint.Lines 13–14: The midpoint of the two points is calculated, and the members of the
m
structure variable are updated.Lines 20–21: Structure variables for two points,
p1
andp2
, are declared and initialized.Line 22: An
m
structure variable is declared, and themidpoint()
function is called withp1
andp2
as its arguments.Line 23: The members of the
m
structure variable are accessed and printed.
Structure manipulation with pointers
We’ll now explore how we can use structure manipulation with pointers. Like other data types, we can make a pointer of the structure data type (user-defined data type). We access each member using the ->
(arrow) operator. All of the pointer rules we learned in the previous section also apply here.
Let’s look at an example:
#include <iostream>using namespace std;struct Point2D{int x;int y;};int main(){Point2D* p = new Point2D{}; // This will declare one Point2D objectp->x = 10; // or (*p).x = 10;(*p).y = 20; // or p->y = 20;cout << "X cordinate: " << p->x << endl;cout << "Y cordinate: " << p->y << endl<< endl;delete p; //Deleting the pointer or freeing the space???// This is a dangerous code now,// as this memory is taken away from the program, hence a logical errorcout << "After Deleting Pointer: " << endl;cout << "Pointer p: " << p << endl;cout << "X cordinate: " << p->x << endl;cout << "Y cordinate: " << p->y << endl << endl;p = new Point2D[3]{{1,1},{2,2}, {}};cout << "New Pointer Allocation: " << endl << "Points: { ";for(int i=0; i<3; i++){//All three of the below methods to access array are validcout << "("<<p[i].x<<","<<p[i].y<<") ";cout << "("<<(*(p+i)).x<<","<<(*(p+i)).y<<") ";cout << "("<<(p+i)->x<<","<<(p+i)->y<<") ";}cout << "}";delete [] p;return 0;}
Lines 4–8: A structure named
Point2D
is declared with coordinatesx
andy
as its members.Lines 12–14: A
p
pointer of the typePoint2D
is declared, and its members are initialized.Lines 19: The
p
pointer is deleted, freeing the allocated space.Line 24–25: Members of
p
are accessed and printed using the->
(arrow) operator.Line 27: The
p
pointer is now pointed at a new memory, an array ofPoint2D
elements.Lines 29–34: A loop iterates over and accesses each array element to print. Accessing each element is done in three different ways, all of which are the same:
Line 32: The
.
(dot) operator is used to access the array elements.Line 33: The array pointer is dereferenced with its address in the round brackets. Each time
i
iterates, the address is incremented, and the next array element is printed.Line 34: The
->
(arrow) operator is used to access the elements. When doing that, we don’t need to dereference the pointer.
Results
The p
pointer is populated with the x
and y
coordinates using the ->
(arrow) operator, but these values are soon set to 0
as we delete the p
pointer (deallocating memory), which means that the value at the pointer memory location is now set to Null
. Later, we set this pointer to a new array of the type Point2D
. Accessing this pointer shows how the p
pointer still exists and is reusable.
Here’s a pictorial version of this concept:
Passing structures by value and by reference
A structure variable can also be passed by reference to a function, which can be useful for updating its members’ values from within the function. Let’s look at an example to see the difference between the two in the code below:
#include <iostream>using namespace std;struct Point2D{int x;int y;};void passByValue(Point2D p){p.x = 20, p.y = 30;}void passByReference(Point2D& p){p.x = 20, p.y = 30;}void printPoint(Point2D p){cout << "("<<p.x<<","<<p.y<<")"<<endl;}int main(){Point2D p{}; // initialize p.x = 0, p.y = 0cout << "Initial Value of p: ";printPoint(p);passByValue(p);cout << "Value of p after passByValue: ";printPoint(p); // p will be the samepassByReference(p);cout << "Value of p after passByReference: ";printPoint(p); // p will be updatedreturn 0;}
Lines 4–8: A structure named
Point2D
is declared with coordinatesx
andy
as its members.Lines 10–13: A function named
passByValue()
is defined, which takes aPoint2D
variablep
passed by value as its parameter, updating the members ofp
.Lines 15–18: A function named
passByReference()
is defined, which takes aPoint2D
variablep
passed by reference as its parameter, updating the members ofp
.Lines 20–23: A helper function named
printPoint()
is defined, which prints the members ofPoint2D
variables.Line 27: A
p
structure variable of typePoint2D
is declared (with members initialized toNull
).Lines 31–32:
passByValue()
is called andp
is passed as its argument, and the helper functionprintPoint()
is called to print elements ofp
.Lines 35–37:
passByReference()
is called andp
is passed as its argument, and the helper functionprintPoint()
is called to print elements ofp
.
Results
We can see how when the passByValue()
function is called, the values of the members of p
are still 0
, which confirms that when arguments are passed by value, they are not updated at their original addresses. On the other hand, the values of the members are updated at their original addresses when the passByReference()
function is called, and the arguments are passed by reference.
That’s all that the structure in C++ entails. Let’s test ourselves to see if we can implement the above techniques in a practical coding example.
Exercise: Division using struct
Write a function that takes two integers (dividend and divisor) as input and returns two values (quotient and remainder) using struct
in the coding example given below.
#include <iostream>using namespace std;struct Pair{int v1;int v2;};Pair divide(int dividend, int divisor){//Write your code here//Function should return a structure variable of structure "Pair"}int main(){Pair P = divide(19, 5);int quotient = P.v1;int remainder= P.v2;cout << "Quotient: "<<quotient<<endl<< "Remainder: "<<remainder<<endl;return 0;}
If you have trouble getting to the solution, you can click the “Show Solution” button to see how to solve the problem.