...
/Integrating Structures with Arrays, Functions and Pointers
Integrating Structures with Arrays, Functions and Pointers
Learn about using structures in structured programming constructs like arrays, functions, and pointers.
We'll cover the following...
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
Datestructure is declared, having threeinttype variables:day,month, andyear.Lines 11–15: The
Personstructure is declared, having astringtypenamevariable and adobstructure variable.Line 19: A
pstructure variable of thePersonstructure is declared and initialized, also initializing thedobstructure variable of theDatestructure inside the curly brackets separated by the comma.Line 20: The
stringtypenamevariable is printed by using a single.operator functionality.Line 21: The
dobstructure 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
Studentstructure is declared.Line 13: An
arrayof data typeStudentof length3is declared.Lines 15–17: Array elements are initialized at each index.
Lines 19–23: A
forloop is used to iterate over thestudentsarray 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
Rectangleis declared withlengthandwidthas its members.Line 10: The
areafunction is declared, and therstructure variable of theRectanglestructure is given as its parameter.Line 12: The
areaof the rectangle is calculated by taking the product of the members of the structure variable and is returned.Line 17: An
rstructure 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
Point2Dis declared with coordinatesxandyas its members.Line 10: A
midpointfunction of the typePoint2Dis declared, which takes twoPoint2Dvariables to compute their midpoint. It’s important for the function to have the same return type as thePoint2Dstructure because we have to return a structure variable.Lines 12: An
mstructure variable is declared, which stores the midpoint.Lines 13–14: The midpoint of the two points is calculated, and the members of the
mstructure variable are updated.Lines 20–21: Structure variables for two points,
p1andp2, are declared and initialized.Line 22: An
mstructure variable is declared, and themidpoint()function is called withp1andp2as its arguments.Line 23: The members of the
mstructure 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
Point2Dis declared with coordinatesxandyas its members.Lines 12–14: A
ppointer of the typePoint2Dis declared, and its members are initialized.Lines 19: The
ppointer is deleted, freeing the allocated space.Line 24–25: Members of
pare accessed and printed using the->(arrow) operator.Line 27: The
ppointer is now pointed at a new memory, an array ofPoint2Delements.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
iiterates, 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
Point2Dis declared with coordinatesxandyas its members.Lines 10–13: A function named
passByValue()is defined, which takes aPoint2Dvariableppassed by value as its parameter, updating the members ofp.Lines 15–18: A function named
passByReference()is defined, which takes aPoint2Dvariableppassed by reference as its parameter, updating the members ofp.Lines 20–23: A helper function named
printPoint()is defined, which prints the members ofPoint2Dvariables.Line 27: A
pstructure variable of typePoint2Dis declared (with members initialized toNull).Lines 31–32:
passByValue()is called andpis passed as its argument, and the helper functionprintPoint()is called to print elements ofp.Lines 35–37:
passByReference()is called andpis 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.