Getting a runtime error while passing a function - c++

I am writing a function that takes an integer "size" as input and returns a 2d vector which is filled spirally from 1 to size*size. So, I created 4 additional functions to traverse left, right, bottom and top. All functions are working correctly except bottom function. Here, i am providing a part of the whole code that is necessary to resolve the problem.
Error :- Your submission stopped because of a runtime error. ex: division by
zero, array index out of bounds, uncaught exception.
I am getting a runtime error when i am passing a "right" function and a "bottom" function. The problem is in the function but I am unable to resolve it. The right function is passing smoothly but the problem is with the bottom function.
void right(vector<vector<int>> &A,int &row,int &column,int &total_elements,int size)
{
if(total_elements==0) return;
while(A[row][column]==INT_MIN && column<size)
{
A[row][column]=1+A[row][column-1];
column++;
total_elements--;
}
column--;
return;
}
void bottom(vector<vector<int>> &A,int &row,int &column,int &total_elements,int size)
{
if(total_elements==0) return;
while(A[row][column]==INT_MIN && row<l)
{
A[row][column]=1+A[row-1][column];
row++;
total_elements--;
}
row--;
return;
}
vector<vector<int> > Solution::generateMatrix(int size) {
int total_elements=size*size;
vector< vector <int> > arr(size, vector <int> (size, INT_MIN));
arr[0][0]=1;total_elements-=1;
int row=0;
int column=1;
right(arr,row,column,total_elements,size);
row++;
bottom(arr,row,column,total_elements,size);
column--;
return arr;
}

Related

Is there a way to find the INDEX of the minimum value in an array using a recursive function? C++

I need to find the Index of the minimum number in an array using a recursive function in c++ the function can only get 2 parameters: the pointer to the array and the size of it.
int smallest(int arr[], int num);
I managed to do this but with a helper variable that is static and declared outside the function here is what I got:
static int flag = 0;
int smallest(int* arr, int num) {
if (flag == num - 1)
return flag;
if (arr[num - 1] > arr[flag]) {
return smallest(arr, num - 1);
} else {
flag++;
return smallest(arr, num);
}
}
Now my question is can I do this without the static variable or any other variable other than the num? here is what I got so far:
int smallest(int arr[], int num) {
if (arr != &arr[num - 1])
if (*arr < arr[num - 1])
smallest(arr, num - 1);
else
smallest(arr + 1, num);
return num - 1;
}
It doesn't return the index of the minimum value but it does get to its adress, the function ends when the array pointer address is the same as the address of the minimum value. how can I get it to return the index?
I'm a student and I'm pretty new to C++ I appreciate the help! thanks!
===
edit:
this is originally from a homework assignment but the constraint to not use external help variables or functions is mine! and I'm curious to know if its even possible.
Because this is obviously homework, I'm not going to reveal the ACTUAL answer in entirety, but I'll give some (hopefully) good advice.
With recursion, think first of what your end condition is. That should be an array of 1 element. You return the index 0 in that case because of the array you have, it's the only element, so return the index of it.
if(num == 1)
{
return 0;
}
So then how is that useful to you? Compare it to exactly one other element. That's how you break this down. Your array turns into "one element and MANY" or "It's just one element." If it's just one, return the only value. If it's many, call yourself recursively from the second element (index 1) onward:
int restOfArraySmallest = smallest(arr+1, num-1) + 1;
You need the +1 because you've offset where it starts from. But you know the value in restOfArraySmallest is the index into YOUR arr of the smallest value of everything except the first element. Because your recursive calls don't include the first element, just the rest.
Hopefully that's enough to get you the rest of the way.
Edit: Because the OP has responded and said it wasn't essential to their homework assignment, here's the entire function:
// Recursively finds the index of the smallest element of the passed-in array
int smallest(int* arr, int num)
{
if(num <= 1)
{
return 0; // If we're in the last element, the smallest is the only element
}
// More than one element, so find the least element in all the elements
// past the first element of the array
// Note: the index returned is offset from our current view of the array,
// so add +1 to any returned result so we can index directly from it
int restOfArraySmallest = smallest(arr+1, num-1) + 1;
// Compare the first element in the array to the smallest of the entire rest
// of the array:
if(arr[0] < arr[restOfArraySmallest])
{
// The first element is smaller, it's the smallest, so return that index
return 0;
}
else
{
// The element already found is smaller, so return that index. It's already
// correctly offset
return restOfArraySmallest;
}
}
And that's it. If there's duplicate entries for smallest, it will favor the LAST one.
The trick with recursion is to NOT keep external variables. What you pass as the arguments and RETURN BACK are all the information you have. For some algorithms, it's enough.
Note, if you use recursive functions with datasets big enough, you will eventually get a Stack Overflow. Not the website, the crash type. This algorithm is pretty light in that only one extra variable and the two arguments themselves get allocated each pass, but it adds up eventually.

Why is my variable not increasing after each recursion?

So I'm pretty new to C++ and I'm trying to generate Fibonacci numbers using recursion right? Except when I try to index to the next value I need to increase the index, and the function won't let me increase it.
How I know, is that I've run it in debug mode and stepped over the function - it continuously loops inside the fibGen function with i staying at a constant value of 1 (When I call fibGen in my main function the parameters are (startingSeq, 1, 13), where startingSeq is another vector with values {1,1}
The code builds and compiles fine, but when I run it I get a memory alloc error, which is obv caused by the infinite loop it seems to have.
What have I done wrong? Why doesn't the 'i' increase?
I've tried increasing i by having i++ inside the recursive fibGen call (in the else statement), I've tried having i++ outside the function call, and I've tried what's in there right now, where I have i+=1 and then pass i through.
Also I didn't have the 'return fibSeq' down the bottom originally because it doesn't make sense to have it there, but I put it in because vscode wouldn't compile without it in there, saying that it could never reach the end of fibGen (which makes sense now, and when this problem's fixed I think it can be removed, but at the moment it's just there so that the program will compile)
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
return fibSeq;
}
The output should be a vector containing the Fibonacci sequence, and I'm getting a mem alloc error (described above)
Actually, your code kind of works. You are just handling the vector of results sub-optimally. With your declaration:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max)
you will always pass copies of the vector around (and you are never using the returned value). Instead, what you probably want to do is to work on the same data. To do this, use a reference to a vector (denoted by &). Then, you do not need to return anything:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
void main(void) {
std::vector<int> fib = { 1, 1 };
fibGen(fib, 1, 34);
for (auto i : fib)
std::cout << i << std::endl;
}
So, I could not reproduce the error, until I realized that in your actual code, you were doing this instead of the code you posted:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
fibGen(fibSeq, i, max);
}
}
In Visual Studio 2010, at least, it compiled fine, but threw an error at runtime, which I believe is what you described. So I'm going to assume I reproduced it.
The reason this is throwing an error is because you are invoking C++'s infamous undefined behavior. Undefined behavior in C++ permits anything to happen, like not failing to compile, but throwing a runtime error.
The fix is simple, really. You just need to return a value in all execution paths. Or, simply put, just do this:
std::vector<int> fibGen(std::vector<int> fibSeq, int i, int max){
if(fibSeq[i] >= max){
return fibSeq;
}else{
fibSeq.push_back(fibSeq[i] + fibSeq[i-1]);
i+=1;
return fibGen(fibSeq, i, max);
// Notice we are returning the value of the recursive call to fibGen().
// We can do this because we have already modified the vector the way we need to,
// so just simply returning the value is fine
}
}
Of course, you can take Nico Schertler's suggestion instead too:
void fibGen(std::vector<int>& fibSeq, int i, int max) {
if (fibSeq[i] >= max) {
return;
}
else {
fibSeq.push_back(fibSeq[i] + fibSeq[i - 1]);
i += 1;
fibGen(fibSeq, i, max);
}
}
It should be noted that not returning a value from a void function is not undefined behavior (that I'm aware), but actually how void's intended to work, so this function is fine not returning a value.

Passing into a function a part of my matrix (2d array)

In my program im trying to add the values of a sub-part of my 2d array, a small box of 3 by 3 from a 9 by 9 matrix. Im choosing that small box by the % of rows and columns by 3(modulus 3). (meaning it will take cells like [0][0], [0][3], and so on )
which i want those to be my top right corner of the box and then add 2 more rows and columns making it for instance if we started at [0][0] we will add [0-2][0-2] (3 by 3 box). Im calculating that through a function (as a practice to use functions). The problem is that the program seems to only take in the value of the first cell from that small box, and when i try to loop on the rest of that small box, and add their values, it doesnt take the values correctly (or at all)
i want to know if my parameters are wrong, or im giving the function wrong parameters.
any help would be appreciated.
//------------including section-----------
#include <iostream>
#include <cstdlib>
//------------using section---------------
using std::cin;
using std::cout;
using std::endl;
//-----our constants and variables---------
const int N=3; //initializing our rows and cols as constants
int counter=0, arr[N*N][N*N];
int sumofrow=0, sumofcol=0,sumsquare=0;
//-------prototypes----------------
void READ_MATRIX(int arr[][N*N]);
bool issquare(int arr[][N*N],int row, int col);
//-------main-------------
int main()
{
//calling on the function to input our matrix
READ_MATRIX(arr);
//checking what functions returned
if(counter==0)
cout<<1;
else
cout <<0;
return EXIT_SUCCESS;
}
//-----functions--------
//----readmatrix------
void READ_MATRIX(int arr[][N*N])
{
for (int row=0; row<N*N; row++)
for (int col=0; col<N*N; col++) {
cin >> arr[row][col];
if (row%3==0&&col%3==0)
issquare(arr, row, col);
}
}
//---------issquare-------------
bool issquare(int arr[][N*N],int row, int col)
{
sumsquare=0;
for (int r=0;r<3;r++) //trying to loop on values of array
for (int c=0;c<3;c++)//trying to loop {
//r+row(because row is passed into the function at 0,3,6)
//same for col.
sumsquare+=arr[r+row][c+col]; // this is where it goes wrong
}
//checking to see if sum reached a certain value..
if (sumsquare==45)
return true;
else {
counter++;
return false;
}
}
You are adding values before you accept them. For example, when row = 0 and col = 0 in function READ_MATRIX(), you call issquare() before all values under that 3x3 box are accepted. In case you have initialized all values to zero, the only value contributing to your sum is the first value i.e. arr[0][0].
What you need to do is trigger issquare() function for row = 2,4,8 and col = 2,4,8. Inside the function issquare(), index the array as arr[row-r][col-c].
The error is that issquare() is called before the values it uses have been assigned/read. At the call to issquare(), of all values used in that function, only arr[row][col] is known yet.
What you have to do is to first read the data completely, and only then look at their properties.
Your function issquared is getting called on the first element of your array.
>>> 0 % 3
0
So you are trying to access values outside of your array. CLARIFICATION: They are not initialised yet so they do not belong to your array just yet (this is an over-simplification, the issue is related to memory allocation which I don't know if you have started yet)
Change the line:
if (row%3==0&&col%3==0)
To:
if ((row != 0 && col != 0) && (row%3 == 0 && col%3 == 0))
Also I'd suggested doing a similar check for the last element just to make sure your smaller box is within the boundaries of your matrix.

C++ vector segmentation error when accessing the first element

I've been having a really hard time with this error, as I've tried everything I could to fix it to no avail.
I'm building a genetic algorithm for my C++ class and I have to store a lot of individuals in a container of some sort, so I chose to make a custom container class called "GenePool" to hold instances of "IndivPtr" (which is a typedef smart pointer to "Individual").
These individuals are stored in its internal vector, and I overloaded the subscript operator ([]) to access its elements.
However, my program barely runs because after filling the vector with elements, it always causes a segmentation error when trying to access the FIRST element from the vector, and it throws an std::out_of_range exception!
I would like to know in this case how I can access elements from my vectors without causing such error.
Here is the code for GenePool:
#include "GenePool.h"
#include "Controller.h"
#include <algorithm>
GenePool::GenePool()
{
// Default empty constructor
individualList.reserve(10000);
}
GenePool::~GenePool()
{
//deleteAll();
}
void GenePool::sortPool()
{
// Sort the vector from greatest to least using GreatertThanSort
// The third parameter is the address of the GreaterThanSort's greater than function for a GreaterThanSort for Individuals
std::sort(individualList.begin(), individualList.end(), &GreaterThanSort::greaterThan);
}
Individual& GenePool::operator[](int index)
{
// Put exception handling here somewhere (a throw statement)
return *individualList.at(index);
}
// Get an individual from the list between index 0 and index size - 1
Individual& GenePool::getRandIndiv()
{
return this->operator[](Controller::getRandNumInRange(0, this->size() - 1));
}
void GenePool::pushBackIndiv(const IndivPtr& indiv)
{
individualList.push_back(indiv);
}
void GenePool::pushBackIndiv(Individual& indiv)
{
Individual * p2Indiv = &indiv;
if(LangermannPoint * pIndivL = dynamic_cast<LangermannPoint*>(p2Indiv))
{
IndivPtr pL(new LangermannPoint(*pIndivL));
individualList.push_back(pL);
}
else if(CurveParams * pIndivC = dynamic_cast<CurveParams*>(p2Indiv))
{
IndivPtr pC(new CurveParams(*pIndivC));
individualList.push_back(pC);
}
}
int GenePool::size() const
{
return individualList.size();
}
void GenePool::clear()
{
if(!individualList.empty())
{
individualList.clear();
}
}
void GenePool::addContentsOf(GenePool& other)
{
for(int i = 0; i < other.size(); ++i)
{
pushBackIndiv(other[i]);
}
}
Before this subscript is called, the vector is filled:
// Initialize a population of individuals with randomly generated parameters.
if(getProblemType() == Controller::OPTIMIZATION)
{
for(int i = 0; i < getInitPopSize(); ++i)
{
population.pushBackIndiv(IndivPtr(new LangermannPoint(getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND),
getRandFloatInRange(0.0f, LangermannPoint::POINT_BOUND))));
}
}
else
{
for(int i = 0; i < getInitPopSize(); ++i)
{
population.pushBackIndiv(IndivPtr(new CurveParams(getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND),
getRandFloatInRange(-CurveParams::PARAM_BOUND, CurveParams::PARAM_BOUND))));
}
}
Here is the invocation to the subscript operator that always crashes:
bool Controller::terminationCondition()
{
population.sortPool();
// After sorting, the first is the fittest
if(generationCount <= 1)
{
setSolution(population[0]);
return false;
}
else if(getSolution() < population[0] && generationCount < MAX_GEN_COUNT)
{
setSolution(population[0]);
return false;
}
else
{
return true;
}
}
First of all, in pushBackIndiv you should add an else for the case of error where it is not LangermannPoint or CurveParams. It seems the problem is not here but you should add that in it will help you.
Second, in operator[](int index), before accessing an element check if the requested index won't give you an out-of-range. You can check this comparing with individualList.size().
Also call size() to see if you actually have elements in the list.
Alright, so it turns out that the real reason why I kept getting this error was because of a silly mistake on my part: I forgot to initialize the size of the population, so it never added elements to the vector when I thought it did.
But thankfully, I learned all about segmentation errors through investigating this error and how to make a vector of abstract data types :)

Array setup in constructor means failure later on

I had an issue where my code segfaulted on attempting to use the size() function of a list. On the advice of stackoverflow :-) I constructed a minimum case in which the segfault occurs (on the call inventory.size() below). It is:
#include <list>
class Thing {};
class Player {
private:
int xpCalcArray[99];
std::list<Thing*> inventory;
public:
Player();
int addToInv(Thing& t); // return 1 on success, 0 on failure
};
Player::Player() {
// set up XP calculation array
for (int i=1; i<100; i++) {
if (i<=10) {
xpCalcArray[i] = i*100;
}
if (i>10 && i<=50) {
xpCalcArray[i] = i*1000;
}
if (i>50 && i<=99) {
xpCalcArray[i] = i*5000;
}
}
}
int Player::addToInv(Thing& t) {
if (inventory.size() == 52) {
return 0;
} else {
inventory.push_back(&t);
}
return 1;
}
int main(int argc, char *argv[]) {
Thing t;
Player pc;
pc.addToInv(t);
return 1;
}
I notice that when I remove the setting up of the array in the Player cosntructor, it works fine, so this looks to be the problem. What am I doing wrong?
You are accessing your array out of bounds, which results in undefined behaviour. The valid index range for this array
int xpCalcArray[99];
is 0 to 98. You are accessing index 99 here:
if (i>50 && i<=99) {
xpCalcArray[i] = i*5000;
}
Your outer loop should be
for (int i=0; i<99; i++) { ... }
Note I start from 0, although it is an assumption that you actually want to access the first element.
Then your final condition can be simplified to
if (i>50) {
xpCalcArray[i] = i*5000;
}
If you intended to use a size 100 array, then you need
int xpCalcArray[100];
then loop between int i=0; i<100;.
You are accessing outside the bounds of your array. Doing so causes undefined behaviour and so there is no logical explanation for anything that occurs afterwards. The size of your array is 99 and so the last index is 98. Your for loop goes up to 99, however.
Either make your array size 100:
int xpCalcArray[100];
Or change your for condition to i < 99.
You are overwriting your array of 99 ints by attempting to modify the 2nd→100th elements (rather than 1st→99th).
In your case, this happens to overwrite some memory within the std::list<Thing*> (which exists in memory directly after the array — not always, but evidently for you today) and thus, when you try to use the list, all hell breaks loose when its internal member data is no longer what it thought it was.
You xpCalcArray is defined from 0 up to 98 (being 99 elements large).
Your loop goes from 0 up to 99, taking 100 steps.
The last loop cycle, writes xpCalcArray at location 99, which does not exist. This (indirectly) results in your segmentation fault as shown by the answer of Lightness Races in Orbit.
So, increase the size of xpCalcArray by 1:
int xpCalcArray[100];