Element Replication

Motivation

When one decides to take a paid on-line course there may be one or more reasons behind it. I can think of a few. You need or want to learn the skills offered by the course. You might just want to refresh and/or learn new things. Or you might just want to have the completion certificate that you finished and met the requirements for the course to get a diploma. I personally like to refresh, learn, and have proof that I actually completed the course.

Situation

The paid on-line course I am attending on weekends has the following chapter components:

o Chapter introduction by the original author of the course.

o Graphical presentations for the subject matter of the chapter. The presentations include audio.

o An introduction problem that provides an overview of the contents of the current chapter. The problem in this post is related to this component.

o Preliminary questions for a section within a chapter which are not graded.

o Problems assigned to the students to solve. Descriptions are made available and the code offered as a solution is graded.

o Final questions regarding the material presented in the chapter. Each correct answer is worth one point. Sometimes you have a single opportunity to answer, and other times you can get two or three attempts.

The problem we are covering in this post is the introduction to the chapter that deals with exceptions.

Problem Description

Since I tend to describe the problem between tags to show what
the proposed requirements are, I will do so for this code.

We are interested in illustrating how to use exceptions in C++.

A teacher gives her students (in this case us) and assignment. The students must 
store numbers in an array of a specified capacity. The teacher would then provide 
an index into the array. The studentss must copy the value of the elementfrom the 
specified position and append it to the array.

We must implement this logic in C++ using concepts of arrays and exceptions.

We need to develop the elementReplication() function which prompts and gets the 
size for an int array, prompts and gets the values that should be inserted into 
the array.

The program whould then prompt the user for an indexed position in the array in
order to replicate / append the value of the specified index at the end of the array.
If the specified index is beyond the size of the array; throw a runtime error exception
with the meaage "Array index is out of range". 

In the main() method we must use an exception handling mechanism.

In a nutshell we are given the size of an array. We then enter values for the array. We are then given a position in the array and need to append to the array the value at the specified index.

The core of the problem is to determine if the index entered by the user is valid or invalid. If all is well, the value is appended and the array is displayed. If it is not valid, the function of interest needs to throw an exception which should be caught by the main() function. 

Test Runs

Before we look at the code let’s take a look at a couple passes of the program. The output was collected on the console created by Visual Studio 2020.

>>> size of array: 3
elementReplication <<< n: 3
>>> array elements: 1 2 3
elementReplication <<< ar: 1 2 3
>>> position of element to replicate: 2
<<< ar: 1 2 3 3


>>> size of array: 3
elementReplication <<< n: 3
>>> array elements: 1 2 3
elementReplication <<< ar: 1 2 3
>>> position of element to replicate: 3
main <<< elementReplication - array index out of range

In the first test case the size of the array is 3. The value is displayed to verify that all is well so far. The user (as illustrated in the training video) entered 1 2 3. The values now in the array `ar` are displayed to make sure we follow what is happening.

The user enters a 2 so our program needs to append to the array ar[2] == 3 and then display the array. It seems that the proper value was appended. No need to throw an exception.

In the second test case we are given once again a size of 3. It seems we enter the same three values. This time we are asking the program to append the value at location 3. Since our array only has locations, 0, 1, and 2 it has to throw an exception. Our main() function seems to have caught the exception.

Actual Code

The C++ code was implemented and tested using the Visio Studio 2022 development tool. The code was compiled using the Cpp20 settings. The actual code was written using different syntax of C++.

#include <iostream>
#include <exception>

using namespace std;

The header section contains the included files and the namespace used to simplify the source code.

/// <summary>
/// Test scaffold
/// </summary>
/// <returns></returns>
int main()
{

    // **** initialization ****
    int retVal{0};

    // **** try-catch block ****
    try
    {
        elementReplication();
    }
    catch (bad_alloc &e)
    {
        // **** memory allocation exception ****
        cerr << "main <<< " << e.what() << endl;

        // **** flag the issue ****
        retVal = -1;
    }
    catch (runtime_error &e)
    {
        // **** runtime exception ****
        cerr << "main <<< " << e.what() << endl;

        // **** flag the issue ****
        retVal = -2;
    }
    catch (exception& e)
    {

        // **** other exception ****
        cerr << "main <<< EXCEPTION - " << e.what() << endl;

        // **** flag the issue ****
        retVal = -3;
    }

    // **** assume all went well ****
    return retVal;
}

This is the test scaffold.

The code is quite simple. We make a call to the function of interest and check if an exception is thrown. Note that in the actual code, the function of interest precedes the main() function. If this would not be the case, the compiler would have indicated an error and we would have had to define the function before or include a forward definition.

We are checking for two specific exceptions plus a general catch all.

/// <summary>
/// It is clear that the person describing the problem 
/// in the video does not understand C++.
/// </summary>
void elementReplication()
{

    // **** initialization ****
    int n{0};
    int pos{0};

    // **** prompt for and read n ****
    cout << ">>> size of array: ";
    cin >> n;

    // ???? ????
    cout << "elementReplication <<< n: " << n << endl;

    // **** allocate memory for array ****
    //int arr[n];             // !!! does NOT COMPILE !!!
    int* ar = (int*)calloc(n + 1, sizeof(int));

    // ???? test memory allocation failure ????
    //ar = NULL;

    // **** check if malloc failed ****
    if (ar == NULL)
    {
        throw bad_alloc();
    }

    // **** prompt for values and populate array ****
    cout << ">>> array elements: ";
    int* p = ar;
    for (int i = 0; i < n; i++, p++)
    {
        cin >> *p;
    }

    // ???? ????
    cout << "elementReplication <<< ar: ";
    for (int i = 0; i < n; i++)
        cout << ar[i] << ' ';
    cout << endl;
 
    // **** request and accept position of element to replicate ****
    cout << ">>> position of element to replicate: ";
    cin >> pos;

    // **** verify position to replicate ****
    if (pos >= 0 && pos < n)            // REPLACE n with n - 1
    {

        // **** for the looks ****
        cout << "<<< ar: ";

        // **** replicate this element
        //      may be OUT OF BOUNDS (like in the demo code) ****
        ar[n] = ar[pos];

        // **** display contents of array ****
        for (int i = 0; i <= n; i++)
        {
            cout << ar[i] << " ";
        }
    
        // **** for the looks ****
        cout << endl;
    }

    // **** need to throw an exception ****
    else
    {
        throw runtime_error("elementReplication - array index out of range");
    }
}

This is our main() function.

We start by declaring and initializing two variables. The initialization is something I tend to do. The problem did not initialize the variables.

After getting the number of elements for the array, the array is declared. The original code used a statically declared array. Apparently C++20 prefers dynamic allocated arrays. I allocated an array with `n` elements to match the original code.

The program then prompts for the values for the `n` elements. The values are set in the array. All is well so far.

The program now requests for a position in the array which we will replicate at the end.

Our code checks the value in `pos` incorrectly since the elements in an array of n elements are in the range [0, n – 1].

The code then assigns to ar[n], which is out of bounds, the value of ar[pos]. During the description the comment is made that the array will be dynamically grown to accommodate the replicated element. This is completely wrong in C and C++.

The program goes ahead and displays the contents of the array without showing a problem. In this case no exception is thrown.

Course Structure

The course is divided into about ten chapters. There is a quick test without grading to determine what you know about the subject. Each chapter contains one or more videos in which the subject for the chapter is presented by the instructor. You do not see or hear about him until the next chapter.

Following is a demonstration. The demonstration for the chapter in question is what we saw earlier. The code was for an earlier version of C++. I just made changes to reflect my use of C++20.

Next are six to ten problems which are poorly defined. Code skeletons are provided for each problem. Some of the skeletons are incorrect (e.g., function / method defined as void, yet it may return a different type value).

The last problem tends to be similar to the demo problem. We will go into the final problem of the same chapter for which the code was shown earlier in the post.

I have not shown the descriptions for the problems due to the fact that if you agree to take the course and pay for it, you are not allowed to copy the contents of the course. I wonder why!

Enter the size of an array
4
Enter the array elements
1 
2
3
4
Enter the index position of the element in the array to be replicated
2
1       2       3         3


Enter the size of an array
3
Enter the array elements
1
2
3
Enter the index position of the element in the array to be replicated
3
Array index is out of range

We are prompted for the size of the array. The size is then collected.

We are then prompted to enter the values for the array. The values are entered.

We are prompted for the index in the array to replicate. The value is entered.

In the first case all seems to go well. In the second example an exception is thrown. Seems reasonable since we were asked to replicate the element at position 3 when our array only has positions 0, 1, and 2.

By the way, this was a problem so I generated my solution.

#include <iostream>
#include <exception>
//#include <string>

using namespace std;

#pragma warning(disable:6011)

The headers and namespace seems reasonable. In this exercise the include files were specified. I commented out the third include file since it is not required.

I included the pragma to eliminate a warning from the compiler.

/// <summary>
/// Replicate the element at that index and `replace` it with the last element in the array. 
/// If the index specified is beyond the array size, 
/// throw a runtime_error with the error message : “Array index is out of range”.
/// </summary>
void elementDuplication(int* ar, int size, int pos) {

    // **** sanity check(s) ****
    if (ar == NULL || size == 0)
    {
        throw runtime_error("Invalid argument(s)");
    }
    if (pos < 0 || pos > size - 1)
    {
        throw runtime_error("Array index is out of range");
    }

    // **** replicate the element ****
    ar[size - 1] = ar[pos];
}

Let’s look at the function of interest.

We perform some sanity checks. Both may throw an exception.

If the exceptions are not thrown, then we assign the value at `pos` into the last entry in the array.

/// <summary>
/// Test scaffold.
/// </summary>
/// <returns></returns>
int main()
{

    // **** initialization ****
    int size{0};
    int pos{0};
    int* ar = {NULL};

    // **** prompt and get array size ****
    cout << "Enter the size of an array" << endl;
    cin >> size;

    // *** declare array ****
    ar = (int*)calloc(size, sizeof(int));
    if (ar != NULL)
    {
        // **** prompt for array elelemnts and populate array ****
        cout << "Enter the array elements" << endl;
        for (int i = 0; i < size; i++)
        {
            cin >> ar[i];
        }

        //// ???? ????
        //for (int i = 0; i < size; i++)
        //    cout << ar[i] << ' ';
        //cout << endl;

        // **** prompt for the pos of the element in the array to be replicated 
        cout << "Enter the index position of the element in the array to be replicated" << endl;
        cin >> pos;

        // **** duplicate element and display result ****
        try
        {

            // **** duplicate element ****
            elementDuplication(ar, size, pos);

            // **** display array ****
            for (int i = 0; i < size; i++)
                cout << ar[i] << ' ';
            cout << endl;
        }
        catch (exception& e)
        {
            cerr << e.what() << endl;
        }
    }

    // **** assume that all went well ****
    return 0;
}

My approach is similar to what was done in the demo for the chapter.

Of interest is the try-catch block when we call the function elementDuplication(). I decided to pass the array and the size of the array. In C / C++ arrays do not encode their size.

If all goes well we display the modified resulting array. We do not have problems with the description of the problem or the implementation.

Proposed grade: 0 / 100
Note : Once you evaluate your program, it can take a maximum of 15 minutes for the scores to reflect in edX.

Result Description
Unable To Test. Errors In Your Code :
HINTS TO TROUBLESHOOT : Check for Compile Time Errors
AND

Have you used throw keyword or handled exception in main method ?
==============================================================================
Also check whether you have implemented class name/method name/

elementDuplication()

variable names as mentioned in the problem statement.

That said, after returning valid results I received 0 out of 100 points.

How I Approach Solving the Problems for this Course

Before this set of three courses in C++ I took another set of courses for C. The presentation was completely different. The course was generated by an educational institution and the instructors were teachers. This course was generated by a company and it seems that academia was not involved.

The first course in this set of three was acceptable. Occasionally some answers were incorrect. The response from the TAs (Teacher Assistants) was fine.

This second course is full of problems. In addition the TAs do not seem to understand that the reason people take the course is to learn. Based on how the course is structured and presented, they should be motivated to present ways to achieve the expected solution after one or more attempts.

The grading of the problems seems to expect a specific approach. Initially I spent time modifying my code, submitting a solution, and asking for advice. On many occasions the advice was late and short in content.

Due to the lack of support I decided to read the requirements for the programs, copy the provided skeletons, plan an approach and generate the code making sure it matched the expected results. I then present my code and completely ignore grading. Spending time on weekend mornings is all I can do.

Final Remarks

After posting this entry I will send a message with a link to the post to the company that offers the paid on-line course. Will let you know next week my findings.

As usual, I have placed the code in this post in this and this repos in GitHub.

Enjoy and hopefully I have motivated you to evaluate in more detail the on-line paid courses you might be considering to take.

Enjoy;

John

 

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.