Problem Solving: Introduction to Sets (Using Functions)
Learn to read sets from a file and sort and display sets using functions. The main focus of this lesson is reusability.
Now that we know how to pass arrays to functions, let’s practice sets and their operations with functions. This lesson will guide you on how the two implementations (with and without functions) differ. We will especially learn how our code gets reduced in length with the use of functions.
Reading sets from a file
Task: Load the two sets, A and B, from the file.
To load a set from the file, we need to write a function, loadSet()
, which we can call whenever we need to load a set from the file (expecting the ifstream rdr
will be pointing toward the file from where the size and the values of a set should be loaded).
void loadSet(const char Msg[], int S[ ], int &size, ifstream &rdr)
If we have the above loadSet()
function, we can see below how simple it becomes to call and load the two sets.
ifstream rdr("sets.txt");int A[capacity]={}, sizeA,B[capacity]={}, sizeB;loadSet(A, sizeA, rdr);loadSet(B, sizeB, rdr);
In the above two function calls, an array is passed and the size
variable is passed by reference, along with the file reader descriptor, which is also passed by reference.
Let's write down the code for loadSet()
and test it.
Instruction: Use the following playground to write the complete code for all the upcoming tasks in this lesson.
#include <iostream>#include<fstream>using namespace std;void loadSet(const char Msg[], int S[ ], int &size, ifstream &rdr){rdr >> size;cout << "The size of the set "<<Msg<<" : "<<size<<endl;int input, repeatedElement = false;for (int i = 0; i <= size-1; i++){rdr >> input;for (int ei = 0; ei < i; ei++){if (input == S[i]){repeatedElement = true;cout << "\nMust have identical elements in the set!!!\n";cout << "Remaining Elements: ";i--;}}if (repeatedElement == false)S[i] = input;repeatedElement =false;}}void setPrint(const char Msg[ ], int S[ ], int size){// Add your code here.}void sort(int S[ ], int size){// Add your code here.}int main(){const int capacity = 500;int A[capacity] = { 0 }, B[capacity] = { 0 }, sizeA, sizeB;ifstream rdr("sets.txt");loadSet("A", A, sizeA, rdr); // load sizeA many entriesloadSet("B", B, sizeB, rdr); // load sizeB many entries// Displaying the sets// cout << "\n Displaying the unsorted sets \n";// setPrint("A", A, sizeA);// setPrint("B", B, sizeB);}
In line 4, the first parameter is the name (a null terminating character array) of the array/set we would like to load, this is to be displayed on line 7. The second parameter,
int S[]
, passed as a base address of the array, whereloadSet()
should load using the last parameter,ifstream & rdr
. Thesize
variable is passed by reference, which will be first loaded usingrdr
—and based on the size, we will load the set.Notice: We can see the entire loading is done using
S[i]
, regardless of which base address is passed. The entire code is exactly the same as before but instead of the array name, in the function, we use the nameS
(the base address of the passed argument).
In line 6, we load the
size
ofS
.In lines 11–27, the outer loop runs from
0
tosize-1
time, and the inner loop confirms that no value is repeated. In our case, the first call ofloadSet()
will update the arrayA
and the second call will updateB
.In lines 46–47, we look at
main()
and how the loading process now has become very simple. Now, it’s just a call to loadSet(“Any Msg or ArrayName”,Arrayname, size, rdr)
. Note how the two calls run the same code, but the parameters are different (for the first call the base address ofA
and with the second call the base address ofB
loads two different sets). This is the power of function-based modularization of the code.
The
ifstream
readers andofstream
writers are always passed by reference. They are not allowed to make copies. Therefore, they can never be passed by value.
Instruction: For the follow-up tasks, use the above playground to add the codes and practice with functions and arrays.
Displaying the sets
Here, you’ll see how to handle both implementations of sets with only one function. Let’s make the setPrint()
function in which we have three parameters. The first is the message, Msg[]
—a null
terminating character array which we will print on the console. The second is the set, S[]
, that has all the elements. The third is the size
of the set.
void setPrint(const char Msg[], int S[], int size)
We don’t need to write the same code (loops) for both sets separately. We have written the same code in this function, and just have to call this function two times for both sets, A and B.
Previous implementations of printing set A:
cout << "A = {";
for (int ai = 0; ai <= sizeA - 1; ai++)
{
cout << A[ai];
// We don't want to print a comma after last element
if (ai != sizeA - 1)
cout << ", ";
}
cout << "}" << endl;
Printing set B
cout << "B = {";
for (int bi = 0; bi <= sizeB -1; bi++)
{
cout << B[bi];
// We don't want to print a comma after last element
if(bi != sizeB -1)
cout << ", ";
}
cout << "}";
The setPrint
function:
void setPrint(const char Msg[ ],
int S[ ], int size)
{
cout << Msg<<" = {";
for (int si = 0; si <= size - 1; si++)
{
cout << S[si];
if (si != size - 1)
cout << ", ";
}
cout << "}" << endl;
}
Call the setPrint
function for set A:
setPrint("A", A, sizeA);
Call the setPrint
function for set B:
setPrint("B", B, sizeB);
Instruction: Add the printing function, void setPrint(const char Msg[],int S[], int size)
, and call in the main for both sets, A
and B
.
Sorting the sets
Let’s make a sort()
function in which we will pass two parameters, the set S[]
array (we will not call it a base address any further, we will just say the array is passed) and size
.
void sort(int S[ ], int size)
Here’s the code to transform the sorting of the two sets by using functions.
Previous implementation of sorting set A:
for (int t = 1; t <= sizeA - 1; t++)
{
for (int ai = 0; ai + 1 < sizeA; ai++)
{
if(A[ai]>A[ai+1])
swap(A[ai], A[ai + 1]);
}
}
The sorting algorithm for set B:
for (int t = 1; t <= SizeB - 1; t++)
{
for (int bi = 0; bi + 1 < SizeB; bi++)
{
if(B[bi]>B[bi+1])
swap(B[bi], B[bi + 1]);
}
}
Sorting the sets with a function:
void sort(int S[ ], int size)
{
for (int t = 1; t <= size - 1; t++)
{
for (int si = 0; si + 1 < size; si++)
{
if(S[si]>S[si+1])
swap(S[si], S[si + 1]);
}
}
}
Calling the sort()
function for set A in main()
:
sort(A, sizeA);
Calling the sort()
function for set B in main()
:
sort(B, sizeB);
Instruction: Update the above playground with the void sort(int S[], int size)
function and call it in main()
. Make sure to try and write the code by yourself.
-
First, in the step-by-step execution instead of step into () functions, use the step over () option and look at how the
sort()
function changes in the array. -
Now, execute the program again and use the step into () option and see how the passed array gets changed.
After sorting the sets, display the sorted sets A and B again.
Complete implementation
Look at the code below to see the complete implementation:
#include <iostream>#include<fstream>using namespace std;void loadSet(const char Msg[], int S[ ], int &size, ifstream &rdr){rdr >> size;cout << "The size of the set "<<Msg<<" : "<<size<<endl;int input, repeatedElement = false;for (int i = 0; i <= size-1; i++){rdr >> input;for (int ei = 0; ei < i; ei++){if (input == S[i]){repeatedElement = true;cout << "\nMust have identical elements in the set!!!\n";cout << "Remaining Elements: ";i--;}}if (repeatedElement == false)S[i] = input;repeatedElement =false;}}void sort(int S[ ], int size){for (int t = 1; t <= size - 1; t++){for (int si = 0; si + 1 < size; si++){if(S[si]>S[si+1])swap(S[si], S[si + 1]);}}}void setPrint(const char Msg[ ],int S[ ], int size){cout << Msg<<" = {";for (int si = 0; si <= size - 1; si++){cout << S[si];if (si != size - 1)cout << ", ";}cout << "}" << endl;}int main(){const int capacity = 500;int A[capacity] = { 0 }, B[capacity] = { 0 }, sizeA, sizeB;ifstream rdr("sets.txt");// Task 1 - Loading the two setsloadSet("A", A, sizeA, rdr); // load sizeA many entriesloadSet("B", B, sizeB, rdr); // load sizeB many entries// Displaying the unsorted setscout << "\n Displaying the unsorted sets \n";setPrint("A", A, sizeA);setPrint("B", B, sizeB);// Task 2 - Sorting the two sets// Sorting A and Bcout << "\n Sorting the sets \n";sort(A, sizeA);sort(B, sizeB);//Task 3 - Displaying the two sorted setscout << "\n Displaying the sorted sets \n";setPrint("A", A, sizeA);setPrint("B", B, sizeB);}