C++ and recursion with arrays - c++

I've programmed with other languages, but now that I am learning C++, I've found a problem. I am trying to solve a problem with recursion, with a method that takes an array as an argument. I thought about using a public array, maybe, but I can't use the array either way.
From what I've read, it seems to me that it has something to do with the memory. (I thought that, even though it consumes a lot of memory, creating it again with each call would work.)
Here's some code:
static void FindSolution(int row, int column, bool answer[][8][8]) {
for(int i = 0; i < 8; i++)
//Some processing…
bool temp = true;
FindSolution(0, column + 1, answer[row][column] = temp);
}
}
How do I get to actually use the array? Somehow.
The error:
error: array type 'bool [8]' is not assignable
FindSolution(0, column + 1, answer[row][column] = temp);

You have an extra [] on your array. You've declared it as a 3D array, but then you try to assign to it like it is a 2D array. The compiler gets upset because you try to assign a bool value to an array, which is exactly what you are doing:
answer[row][column] = temp;
temp has type bool, but answer[row][column] has type bool[8].
Instead declare the argument without the extra []:
static void FindSolution(int row, int column, bool answer[8][8]) {

You keep incrementing 'column', but you never check it to make sure it doesn't reach 8. When it does reach 8, you're off the end of the array, and you get an error.

There are a few immediate problems with this.
First Problem: Function signature is incorrect
You've declared the third parameter as a 3-dimensional array, but you only want to deal with two dimensions it seems. There are a couple of ways you can redeclare this function to accept a 2D array, for all the options see the accepted answer here. Personally, in this situation I'd go with a template option unless there is a specific reason not to. Something like the following:
template<size_t _rows, size_t _columns>
static void FindSolution(int row, int column, bool (&answer)[_rows][_columns]) {
// todo: Some processing...
}
This allows you to accurately know the size of the array at compile time, of course this won't work so well with dynamically allocated arrays but seeing as you seemed to know the dimensions of the array already at compile time, I figured this wasn't an issue. If it is, check the other ways of passing a 2D array to a function in the link I attached.
Second issue: Recursive call
The second issue is how you're doing your recursive call.
FindSolution(0, column + 1, answer[row][column] = temp);
The result of the assignation of temp to the specific location in the answer array is not the answer array, but rather the value of temp. Effectively the following statement:
answer[row][column] = temp
Is trying to pass a single bool value as a 2-dimensional array, which won't work. In order to correctly call the method again you'll need to do your assignation of temp to the answer array, then call the function again.
answer[row][column] = temp;
FindSolution<_rows,_columns>(0, column + 1, answer);
Should work fine. (Note the explicit template arguments here <_rows,_columns>, this is only needed if you're using the function signature I posted above which made use of templates)

Related

Accessing an Element from an int ** array in C++

I am creating a 2D-Array in C++ and need to pass this array as a parameter in a function. In my function, I need to access an element from the array in order to save it as a value, i.e.:
int lowestPoint(int **arr, int x, int y, int n) {
minVal = *(*(arr+x)+y); // here is where I'm getting the exception
return minVal;
}
I've tried setting minVal to arr[X][Y] and have tried to pass the array in as other variations instead of just **arr but nothing seems to be working.
The array is initialized in my main function as int arr[x][y] and I pass it into another function by casting it as otherFunc(reinterpret_cast<int **>((*arr)[n]), n), and then from that function, send it to lowestPoint by calling int val = lowestPoint(arr,i,j,n). I think these calls could be problematic but I'm uncertain how to fix it - I really have no experience with 2D arrays in C++ and it's soo much simpler in Java. I keep getting an EXC_BAD_ACCESS error for the array, so if anyone has any idea how to fix that, I'd really appreciate it. Thanks!
EDIT:
"n" is the size of the array; for example if it's a 3x3 array, n = 3. I just initialized the array as int arr[n][n] and then stored elements. I know the actual array itself represents the correct value, it just can't access it once I send it to another function.
When you pass the array to the first function using reinterpret_cast((*arr)[n]), instead of passing the pointer to the actual array, you are passing the value in location [0][n] (by using (*arr)[n]) and casting it to **arr. So in essence you get a new array that points to a random location in memory that is equal to the content of that array slot.
I am not sure what you intended to do, but if you wanted to pass the actual array, just pass arr. If you planned to pass a sub-array, this method is incorrect altogether as you pass an offset inside an array and you will get skewed data.
Hope This helps,
Lior

What is an elegant solution to this error from std::find?

I have a class which contains an array which size is unknown at compile time. The array is initialized in the constructor. Then, I have another function that checks if an element is in the array:
class myClass
{
int tab[];
public:
myClass(int array[], int length)
{
std::copy(array, array + length, tab)
}
void myFunction()
{
int x = 8;
int *ptr = std::find(std::begin(tab), std::end(tab), tdc_x);
if (ptr) /* here goes my code */
}
};
I got the following error:
error: no matching function for call to ‘begin(int [0])’
What's wrong with the above piece of code? I know that I can't use std::find with pointers, but my array is an array, not a decayed pointer.
I followed this example. I also included the algorithm header. What am I doing wrong?
I compile my code in C++11.
Edit: I get it now. But how can I do what I want to do in an elegant way?
If I use a pointer instead of the empty array, I won't be able to use std::find.
if I give my array an arbitrary size, I won't be able to copy a bigger array.
What should I do?
int tab[];
The standard doesn't allow empty arrays, but some compilers do as an extension. That doesn't make it legit tho.
If I use a pointer instead of the empty array, I won't be able to use std::find.
Not true, you can still use std::find (s is the size of your tab array).
int *ptr = std::find(tab, tab + s, tdc_x);
if I give my array an arbitrary size, I won't be able to copy a bigger array. What should I do?
Use a std::vector<int>, then call resize()

Misunderstanding of C++ array structure

I'm new to C++ and I learned with different tutorials, in one of them I found an example of code:
I have pointed by numbers of lines, that I completely do not understand;
Does this array in array or something like that?
I can understand the second call, but what is the first doing? There is already
"coordinates[blocks[num]]", aren't there? Why need again blocks(i) ?
How do you make this part of the code easier? Did struct with this arrays
don't make easier getting value from arrays?
Thanks in advance!
// Global vars
Struct Rect {
float left;
}
Rectangle *coordinates;
int *blocks;
coordinates = new Rect[25];
blocks = new int[25];
// in method storing values
const int currentBlock = 0; //var in cycle
coordinates[currentBlock].left = column;
blocks[currentBlock] = currentBlock;
//get element method
const Rect& classA::Coords(int num) const
{
return coordinates[blocks[num]]; //(2)
}
//and calling this method like
Coords(blocks[i]); //(3)
Coords(i); //(3)
// (4)
No, not really. Lots of people will think of them as arrays and even describe them as arrays, but they're actually not. coordinates and blocks are both pointers. They just store a single address of a Rect and an int respectively.
However, when you do coordinates = new Rect[25];, for example, you are allocating an array of 25 Rects and setting the pointer coordinates to point at the first element in that array. So, while coordinates itself is a pointer, it's pointing at the first element in an array.
You can index coordinates and blocks like you would an array. For example, coordinates[3] will access the 4th element of the array of Rects you allocated. The reason why this behaves the same as arrays is because it actually is the same. When you have an actual array arr, for example, and you do arr[4], the array first gets converted to a pointer to its first element and then the indexing occurs.
No, this is not an array of arrays. What it is doing is looking up a value in one array (blocks[num]) and using that to index the next array (coordinates[blocks[num]]). So one array is storing indices into the other array.
I'll ignore that this won't compile, but in both cases you are passing an int to the Coords function. The first case looks incorrect, but might not be. It is taking the value at blocks[i], passing that to the function then using that value to index blocks to get another value, then using that other value to index coordinates. In the second case, you are just passing i, which is being used to index blocks to give you a value with which you index coordinates.
That's a broad question that I don't think I can answer without knowing exactly what you want to simplify and without seeing some real valid code.

Multi-Dimensional Arrays--> Null Object Pointers

I am trying to develop a C++ application. Part of the Application is meant to create and initiate some properties of an Object and then store the object in a multi-dimensional array. Problem is after Object creation and storing the objects in the array, retrieving the Object values gives me pointers to NULL.
Please see code below for exact implementation:
Cell** TestMain::convertToMatrix(){
//char[] lengthArr = arra[0];
//int[][] temp
int rowCount = getCurrentRowCount(); // Gives the row count of the multi-dimensional array
int colCount = getCurrentColCount(); // Gives the column count of the multi-dimensional array
Cell** cellList;
cellList = new Cell*[rowCount];
for (int rowIter=rowCount-1;rowIter>=0; rowIter-- ){
cellList[rowIter] = new Cell[colCount];
for (int colIter=colCount-1;colIter>=0;colIter--) {
Cell *currentCell = new Cell(arra[rowIter][colIter],rowIter,colIter);
//Calculate weights
if (0==currentCell->getValue()) currentCell->setWeight(0);
if (1== currentCell->getValue()) {
if (isEdge(rowIter,colIter)) {
currentCell->setWeight(1);
}
else {
//currentCell->setWeight(1 + getMinimumValue(cellList[rowIter+1][colIter]->getWeight(),cellList[rowIter+1][colIter+1]->getWeight(),cellList[rowIter][colIter+1]->getWeight() ) );
currentCell->setWeight(1 + getMinimumValue(cellList[rowIter+1][colIter].getWeight(),cellList[rowIter+1][colIter+1].getWeight(),cellList[rowIter][colIter+1].getWeight() ) );
}
}
cellList[rowIter][colIter] = *currentCell;
}
}
return cellList;
}
`
Here is the code that performs the checking later in the code:
void StrawberryMain::printField(Cell** arrayOfCells) {
int row=0;
int column=0;
int maxRowCount= getCurrentRowCount();
int maxColCount = getCurrentColCount();
for (;row<maxRowCount;row++) {
Cell *cellArr = arrayOfCells[row];
for (;column<maxColCount;column++) {
Cell currentArrayCell = cellArr[column];
/*if (currentArrayCell==NULL){ // This line throws an error ->No match for ‘operator==’ in ‘currentArrayCell == 0’. Why?
printf("Returned Pointer for Cell was NULL");
}
else { */
printf("%s(%s)|", currentArrayCell.getWeight(),currentArrayCell.getValue());
/
//}
printf("\n");
}
}
When I run the program I get a whole load of nulls printed on my screen as output.( One null for every object supposed stored in the array
I come from a Java background ( although I have dabbled in QT C++ before) so I am a bit miffed why this is happening. As much as I would appreciate an answer I would value an explanation as to why this happens ( or a link which explains why this happens) as I really want to understand the workings of the Language.
Thanks in anticipation.
There are several issues in your code.
As already stated in comments, you have a memory leak issue.
if (currentArrayCell==NULL){ // This line throws an error ->No match for ‘operator==’ in ‘currentArrayCell == 0’. Why?
currentArrayCell as declared in your code is a Cell object. Not a pointer to one. So you aren't comparing if a pointed to Cell is NULL. That line is trying to compare if a Cell == 0. And since you apparently haven't defined an equality operator that could work with a Cell and 0 the compiler raises that error.
With that in mind, you should note that the line Cell currentArrayCell = cellArr[column];
is actually creating a copy of a Cell. It may not be important this time. But if you write similar code where you would modify currentArrayCell, then you would find that any changes are only made to the local copy and not to the element in cellArr.
This line:
printf("%s(%s)|", currentArrayCell.getWeight(),currentArrayCell.getValue());
is most likely not doing what you wanted. s% means you must pass a string (meaning something like a const char*). However, based on your other code I'm guessing that those member functions are returning integers. printf is a low level tool and does not have the ability to convert between data types in that manner. You either need to use the appropriate format specifier for the data type (such as %d for int) or convert the values before passing them to printf.
So what happens when you use the wrong format specifier is that printf tries to byte-wise interpret whatever you actually passed as whatever type the format specifier implies. In your case, it's trying to interpret integers as character pointers. I'm actually surprised this isn't causing a crash instead of just printing nulls.
just to give you an idea
template<typename T>
struct array {
array(int m, int n) {
size_[0] = m, size_[1] = n;
data_.resize(m*n);
}
T* operator[](int i) {
return &data_.front() + i*size_[1];
}
private:
stdvector<T> data_;
size_t size_[2];
};
It seems clear from your code that you're a C guy doing C++, so here are some classes that should be aware of in light of your goals.
Boost's ublas has a matrix implementation that would be a generally superior alternative to creating your own implementation.
Baring that, at bare minimum you should probably be working with vectors instead of dynamically created arrays to reduce the potential for memory leaks.

Declaring char[][512]?

I have an C++ SDK that requires a char[][512] as a parameter. I know that this is supposed to be a list of file names and the number of files could vary. For the life of me I cannot figure out how to declare this. I have an array of CStrings and I am trying to copy them over using strcpy_s and then pass them into the SDK. Any idea on how to do this?
This declaration has a special meaning when used to declare parameter of a function. Within the parameter list it is equivalent to char[100][512], char[123][512], char[3][512] (you get the idea - the first size can be just anything, it is simply ignored) and also to char (*)[512]. Effectively, it will accept as an argument a 2D array of chars with flexible (arbitrary) first size.
The array that you will actually pass to this function should be declared with a concrete first size, for example
char names[3][512] = { "abc", "cde", "fgh" };
if you know the first size at compile time, of course.
If the first size is only known at run time (say, n), you'll have to allocate the array dynamically
char (*names)[512] = new char[n][512];
// Now fill it with names
or, more elegantly, with a typedef
typedef char TName[512];
TName* names = new TName[n];
// Now fill it with names
I expect that the SDK function you are talking about also asks you to pass the first size of the name array as another parameter.
It means 2D array of char. The number of rows could vary, and it should/may be specified in another parameter. C/C++ compilers need to know the number columns when a 2D arrays is passed ,So they can build the mapping function. Simply because arrays decay to pointers when they are passed as parameters, size information is lost. For example:
void fun(char matrix[][512], int rows);
...
char matrix[100][512];
...
fun(matrix, 100);
The mapping function that the compiler construct for a 2D array is similar to:
// arrays in C/C++ are stored in Row-Major Order
matrix[i][j] == matrix[i*numberOfColumns + j]
As you can see, when a 2D array is passed and the size information is lost, we need only the number of columns to index any element in this array.
Here is a way to convert an argv-style array of filenames into the form your SDK needs.
typedef char Char512[512];
Char512 * convert(const char *names[], int n)
{
Char512 * arr;
arr = new char[n][512];
for (int i = 0; i < n; n++)
::strncpy(arr[i], names[i], 512);
return arr;
}
When in doubt, use a typedef.
Just a reminder, if you new[] something, you must delete[] (not delete) it sometime.