Using struct: Exercises and Takeaways
Evaluate yourself on what we've learned about structured programming.
Your playground
Let’s solve some exercises to implement structures for the rest of the arithmetic operations. Again, you’ll write the code in the playground given below. The add()
function is already appended to this widget, meaning the code is present but hidden so that you can use all the helper functions by just calling them. You don’t need to write their entire code.
#include <iostream>using namespace std;struct MixedFraction{int sign; // either will be +1 or -1int w;int n;int d;};//Helper function already appendedint gcd(int a, int b);void improperFraction(MixedFraction &frac);void sameDenominator(MixedFraction &L, MixedFraction &R);void computeSign(MixedFraction & frac);void mixedFraction(MixedFraction &frac);MixedFraction add(MixedFraction L, MixedFraction R);void print(string msg, MixedFraction frac);// The four prototypes for the addition, subtraction, multiplication and divisionMixedFraction add(MixedFraction L, MixedFraction R); // Already imeplementedMixedFraction sub(MixedFraction L, MixedFraction R);MixedFraction mul(MixedFraction L, MixedFraction R);MixedFraction div(MixedFraction L, MixedFraction R);int main() {MixedFraction final= {}; //final fractionMixedFraction left = {+1, 2, 1, 2}; //left fractionMixedFraction right = {-1, 2, 1, 2}; //right fractionprint ("Left", left);print ("Right", right);final = add(left,right); // f =L+Rprint ("Left + Right", final);final = sub(left,right); // f =L-Rprint ("Left - Right", final);final = mul(left,right); // f =L*Rprint ("Left x Right", final);final = div(left,right); // f =L/Rprint ("Left / Right", final);return 0;}//Add function implementation already appenededMixedFraction sub(MixedFraction L, MixedFraction R){MixedFraction result{};// Write your code herereturn result;}MixedFraction mul(MixedFraction L, MixedFraction R){MixedFraction result{};// Write your code herereturn result;}MixedFraction div(MixedFraction L, MixedFraction R){MixedFraction result{};// Write your code herereturn result;}
Exercise 1: Implementing the sub()
function
Write the sub()
function and uncomment the lines in main()
where sub()
is called. If you have trouble getting to the solution, you can click the “Show Hint” button to see how to implement it.
Exercise 2: Implementing the mul()
function
Write the mul()
function and uncomment the lines in main()
where mul()
is called. If you have trouble getting to the solution, you can click the “Show Hint” button to see how to implement it.
Exercise 3: Implementing the div()
function
Write the div()
function and uncomment the lines in main()
where div()
is called. If you have trouble getting to the solution, you can click the “Show Hint” button to see how to implement it.
Remember: We’re updating the parameters received,
L
andR
, multiple times in several functions, such asimproperFraction(L)
,improperFraction(R)
, andsameDenominator(L,R)
. These functions receive parameters by reference and update them. However, the changes made by these functions will not affect the fractions passed as arguments from themain()
function. This is because theadd()
,sub()
,mul()
, ordiv()
functions receive parameters by value. Consequently, any changes made after entering these functions will only impact the local copies of the parameters, not the arguments passed in the callee positions.
Takeaways and issues with the structured approach
Utilizing structuring, which involves grouping similar values as user-defined data types, has several advantages, including:
Ability to return multiple values: By utilizing structures to store multiple variables of different data types as their members, we can easily return multiple values, reducing code complexity and eliminating the need for passing variables by reference.
Data abstraction: Structures enable us to introduce data abstraction. For example, rather than associating three variables for a mixed fraction, we now have a single structure called a mixed fraction. This structure encapsulates them as three-member variables, meaning the user doesn’t need to keep track of every single variable for each mixed fraction and now has an entity that represents a mixed fraction for them. We’ll discuss this concept in later lessons.
Reduced complexity and code size: By comparing the previous code that used primitive data types and the current one that utilizes
struct
from C++, we observe a substantial reduction in code size and complexity. Introducing data grouping throughstruct
enhances code management, resulting in a more modular and comprehensible codebase.
Note: Keep in mind that while structures can be used to return multiple values, it’s not their primary intended purpose, and using them solely for that may not be considered a good programming practice. Instead, reference type parameters should be preferable for this purpose. Structures, on the other hand, excel when dealing with a collection of related data that should be logically grouped together, as was the case in the
MixedFraction
case study. By leveraging structures in such scenarios, we achieve code organization and readability, making our code more robust and maintainable.
Despite the significant improvements we observed in our case study by introducing struct
within the procedural/structured programming paradigm, this approach also has some drawbacks:
All public members: Structure members can be accessed and modified throughout the code’s scope. Consider the scenario of creating a timer
clock
that increments every second. For this purpose, aclock
structure variable is created of atimer
structure with three members:seconds
,minutes
, andhours
. We utilize a built-in library function to increment this timer, which should run independently in the background. However, what if someone unintentionally writes the commandclock.hours = -10
at some point? This would update thehours
member to an incorrect value of-10
. It becomes evident that we need a way to restrict unchecked access to structure members. In a future lesson, we’ll explore a paradigm shift that addresses this issue.Independent functionality: Notice how a structure is nothing but a user-defined data type, a group of variables representing or associating with a certain category. For example, in the
MixedFraction
structure of our case study, all its members contain the data of a mixed fraction. To make a functioning calculator, we make separate functions,add()
,sub()
,mul()
, anddiv()
, which reside outside the structure as independent functions. These functions and data are still scattered, and the complexity is still too much as they both grow independently.
Takeaway question
What if we take it a step further and enhance the code’s modularity? Can we introduce a concept where the structure not only stores data but also encapsulates its functionality? The idea is to integrate related data and its associated functionality within a module, creating a more cohesive collaboration. This approach ensures that each module understands the scope of the data it contains and the functionality it offers. This concept marks the beginning of our new paradigm known as object-oriented programming, which we’ll explore in the upcoming lessons.