Calling a C++ function with an array of arrays [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
I've got a library function I need to call and I'm having trouble with c++ basics for some reason.
The declaration of the function is:
void doSomething(int** values, int length, int width);
It's taking an array of integer arrays. This is fine, I'm having trouble sending getting the data into it.
My data is just 2 integers, say 4 & 5.
In c# I think the syntax would be somethings like: [ [4,5] ]
An array containing an array which contains the two values.
How on earth do you declare this basic structure in C++?
I've tried:
int vals[1][2] = { {4,5} };
doSomething(vals, 1,2);
But the compiler comes back with:
error: no matching function for call to ‘myclass::doSomething(int [1][2], int, int)’
doSomething(vals, 1, 2);
^
src/mysclass.cpp:74:6: note: candidate: void myclass::doSomething(int**, int, int)
This must be simple. There must be a simple way to declare this data to call the function with these values. I'd prefer stack based, if possible.

Parameter int **values denotes a pointer to one pointer (or several consecutive pointers) to one int (or several consecutive ints). The "several consecutive..."-case can be used to represent a "two-dimentional array". Note that values points to an array of pointer values, not to an array of ints. This is different from a data structure like int myArr[10][20], where myArr points to / is an array of arrays of integers.
A simple way to call it is to generate a 1D-array, let an int-pointer point to this array, and pass the address of this pointer:
void test (int** value, int length, int width) {
for (int l=0; l<length; l++) {
for (int w=0; w<width; w++) {
cout << "[" << l << "," << w << "]:" << value[l][w] << endl;
}
}
}
int main() {
int myArr[] = { 4,5 };
int* ptrToMyArr = myArr;
test (&ptrToMyArr,1,sizeof(myArr)/sizeof(int));
}

You could also do something like this:
#include <iostream>
void doSomething(int** value, int length, int width)
{
for (int i = 0; i < length; ++i)
for (int j= 0; j < width; ++j)
std::cout << value[i][j] << std::endl;
}
int main()
{
// array of arrays of int
int arr[2][2] = { { 1,2 },{ 3,4 } };
// convert to array of pointers to int
int *vals[2] = { arr[0], arr[1] };
doSomething(vals, 2, 2);
return 0;
}
https://ideone.com/PgpzK0

Related

When I try to store a character in an array, the array fills with numbers instead c++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 12 months ago.
Improve this question
I'm very new to c++ so all of this is very confusing to me. I'm reading characters from a file using ifstream.get and storing the values in a 2d integer array. The file is just a 9x9 grid of numbers 1 through 9.
So I read the character and when I hover over it in debug mode to see the value, I can see the number represented as a character but also a number written next to it. Apparently this is the address or something. When I print the character to the console, everything is fine. But when I try to store the character in the 2d integer array, it stores the address (or whatever it is) instead.
void Grid::LoadGrid(const char filename[])
{
ifstream inputFile(filename);
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
char c;
inputFile.get(c);
cout << c;
m_grid[x][y] = c;
}
}
inputFile.close();
}
You are getting int values because you are trying to store char in an int array, which leads to conversion of char to int (ASCII value of char). So the int values is basically the ASCII value of the character '0', '1', etc.
If you want to store characters then just store them inside a char array:
char m_grid[9][9];
But still if you need to store the data in an int array, you can do something like this:
#include <iostream>
#include <string>
#include <fstream>
int m_grid[9][9];
int main()
{
std::ifstream inputFile("input.txt");
for (int y = 0; y < 9; y++)
{
for (int x = 0; x < 9; x++)
{
char c;
inputFile.get(c);
std::cout << c;
m_grid[x][y] = (int)c - '0';
}
inputFile.get(); // This will skip '\n'
}
inputFile.close();
}
int ic = c - '0';
For anyone wondering how to fix this

when I call a function it returns a random valued array instead of the "right one" [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 12 months ago.
Improve this question
I'm trying to improve myself in competitive programming and I'm trying to do a easy task in a hard way.
I'm trying to split an array in two arrays (even and odd positions), apply the QuickSort on each of the two and then putting them together once again.
But I have some wrong output, probably I'm getting something wrong with pointers.
int arr[5] = {5, 4, 1, 3, 2};
int** a;
int size = sizeof(arr) / sizeof(arr[0]);
a = makearrs(arr, size);
Here's where I call the function makearrs passing it the array and the fixed size (I could pass 5 but I just calculated it).
Here's the function makearrs
int** makearrs(int* arr, int size){
int size_arr = size / 2;
int even_arr[size_arr + 1]; //[0, 1, 2, 3, 4]
int pair_arr[size_arr + 1];
// Inizializzo
for(int i = 0; i<=size_arr; i++){
even_arr[i] = 0;
pair_arr[i] = 0;
}
int j = 0;
for(int i=0; i<size; i = i+2){ //Lettura sicura, va bene per entrambi i casi.
pair_arr[j] = arr[i];
if(i+1 != size) {
even_arr[j] = arr[i + 1];
}
j++;
}
int ** a = makepairs(pair_arr, even_arr);
return a;
And finally the function makepairs which creates an array of pointers (two-sized) containing the two arrays (even and odd position array).
int** makepairs(int* arr, int* arr2) {
int** ptr = new int*[2];
ptr[0] = arr;
ptr[1] = arr2;
return ptr;
If I try to for-print the resulting
int * even;
even = a[1];
int * pair;
pair = a[0];
for(int i=0; i<3; i++){
cout << even[i];
cout << "\n";
cout << pair[i];
cout << "\n";
I get this output:
4
47398584
1
1
-325478504
47398584
You are returning pointers to the even_arr and pair_arr arrays. But as soon as the function returns, those arrays no longer exist. So it is an error to dereference the pointers to them.
int** makepairs(int* arr, int* arr2) {
int** ptr = new int*[2];
ptr[0] = arr;
ptr[1] = arr2;
return ptr;
So this allocates a new array and puts two values in it, each a pointer to an array. But:
int ** a = makepairs(pair_arr, even_arr);
return a;
Here you pass it pair_arr and even_arr, causing it to create an array with pointers to those two objects -- objects created locally on a stack that will be destroyed by the return statement immediately following.
Any attempt to dereference those pointers after the return is an error since they are pointers to arrays that no longer exist. (If you think they still exist, try to show where they were allocated and how they could be freed. It cannot be done.)
You should use std::vector instead to avoid this problem.
You are returning pointers to local variables. Those local variables cease to exist after your function returns, so the pointers are invalid. Any use of those pointers means your program has undefined behaviour.
Not only that, you don't have a C++ program.
int size_arr = size / 2;
int even_arr[size_arr + 1]; // This is not C++, size_arr needs to be a compile-time constant

Why does passing a 2D array without the complete size of the array still compile and run? [duplicate]

This question already has answers here:
How do I define variable of type int[][26]?
(2 answers)
Closed 2 years ago.
I have written a small program that passes a 2D array to 2 separate functions that store and display the pattern of a chessboard. While the program works perfectly fine, I would like to ask a more technical question that I have not been able to answer myself through my searches.
I am wondering how it is possible that my program compiles and runs when passing the 2D array with ONLY the columns variable specified, but not the rows. For instance void setBoard(char chessboard[][cols]);
Here is the link to the program: https://codecatch.net/post/54969994-76d7-414b-aab6-997d3fef895c
Here is the same code for those of you that don't want to click the link:
#include<iostream>
using namespace std;
const int rows = 8;
const int cols = 8;
char chessboard[rows][cols];
void setBoard(char chessboard[][cols]);
void printBoard(char chessboard[][cols]);
void setBoard(char chessboard[][cols]) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
if(i % 2 == 0 && j % 2 == 0) {
chessboard[i][j] = 'x';
} else {
if(i % 2 != 0 && j % 2 == 1) {
chessboard[i][j] = 'x';
} else {
chessboard[i][j] = '-';
}
}
}
}
return;
}
void printBoard(char chessboard[][cols]) {
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
cout << chessboard[i][j] << " ";
}
cout << endl;
}
return;
}
int main(int argc, char const *argv[])
{
setBoard(chessboard);
printBoard(chessboard);
return 0;
}
To answer the question directly: in C and C++ passing static array as an argument needs all dimensions except the outermost. So, if you have N-dimensional array, you need to specify the sizes of N-1 dimensions, except the leftmost one: int array[][4][7][2]...[3].
Now, to the gory details.
So, let's say you have int a[3];. What is the type of a? It is int [3]. Now, you want to pass it into function. How do you do this? There are two ways: you can either pass the array by pointer to the first element (works in C and C++), or you can pass the array by reference (references are a C++ thing). Let's consider these examples:
#include <iostream>
void foo(int* array, std::size_t len) { // same as foo(int array[],...)
for (std::size_t i = 0; i < len; i++)
std::cout << array[i] << ' ';
std::cout << '\n';
}
void bar(int (&array)[3]) {
for (int n : array)
std::cout << n << ' ';
std::cout << '\n';
}
template <std::size_t N>
void baz(int (&array)[N]) {
for (int n : array)
std::cout << n << ' ';
std::cout << '\n';
}
int main () {
int a[3] = {1, 2, 3};
int b[4] = {1, 2, 3, 4};
foo(a, 3); // BAD: works, but have to specify size manually
foo(b, 4); // BAD: works, but have to specify size manually
bar(a); // BAD: works, but bar() only accepts arrays of size 3
bar(b); // DOESN'T COMPILE: bar() only accepts arrays of size 3
baz(a); // OK: size is part of type, baz() accepts any size
baz(b); // OK: size is part of type, baz() accepts any size
}
Let's consider foo().
foo()'s signature could also be written as void foo(int array[], ...). This is purely syntactic sugar and int array[] means the same as int* array. Note, however, that this only applies to function signatures, everywhere else these syntaxes are not equivalent.
When you call it as foo(a, 3), it's signature is set to accept a pointer to int as first parameter: int* array. But you know that a is of type int [3], so how does it work? What happens is, the pointer to the first element of the array is passed by value. Which means, it is the same as writing foo(&a[0],...). We take the address of the first element, which is then copied into int* array. As you might notice, having a pointer to the first array doesn't tell us anything about the size of the array, we lost this information during conversion from array type int [3] to int *. Which is why we have to supply the second argument that specifies the length of a. We call this implicit conversion an "array to pointer decay". Decay specifically because we were forced to lose important information -- we had it right there in the type, but now we have to have another argument that describes how many elements the array has. A bit stupid and inconvenient, isn't it?
Now consider bar().
In bar() we pass the array type by reference. This is something that C++ has improved upon C. I will not explain what references are, but in general, you can think of them as something that allows you to get the object the way it is defined, without using any convertions to pointers. In this case, the type of array remains int [3], so we have passed in an array and haven't lost any type information. Great! This means, we can use idiomatic C++ syntax to further improve our code. I have replaced the normal for loop, as found in foo(), with a for-each loop, where we just need to supply a variable to store the element (n) and the array (array). Note that this is possible only because array preserves type information! Trying to do this in foo() would result in a compilation error.
However, there is still a problem with this. bar() has to have the array size as part of its signature! This means that if a was any different size, let's say 4 elements, trying to use bar() would result in a compilation error because int [3] and int [4] are incompatible types.
Consider baz(), which solves the above problem.
Just a little bit of templates will make baz() usable on arrays of any size, while the usage stays the same as in bar().
Now, let's take it to multiple dimensions:
#include <iostream>
void foo2d(int (*array)[3], std::size_t rows, std::size_t cols) {
for (std::size_t i = 0; i < rows; i++)
for (std::size_t j = 0; j < cols; j++)
std::cout << array[i][j] << ' ';
std::cout << '\n';
}
void bar2d(int (&array)[2][3]) {
for (std::size_t i = 0; i < 2; i++)
for (std::size_t j = 0; j < 3; j++)
std::cout << array[i][j] << ' ';
std::cout << '\n';
}
template <std::size_t N, std::size_t M>
void baz2d(int (&array)[N][M]) {
for (std::size_t i = 0; i < N; i++)
for (std::size_t j = 0; j < M; j++)
std::cout << array[i][j] << ' ';
std::cout << '\n';
}
int main () {
int c[2][3] = { {1, 2, 3}, {4, 5, 6} };
foo2d(c, 2, 3);
bar2d(c);
baz2d(c);
}
And again, only baz2d() doesn't require hardcoded size information.
One more example, of foo3d(), just to demonstrate what I mean when I say only the outermost dimension doesn't need to be specified:
void foo3d(int (*array)[2][1], std::size_t rows, std::size_t cols, std::size_t K) {
for (std::size_t i = 0; i < rows; i++)
for (std::size_t j = 0; j < cols; j++)
for (std::size_t k = 0; k < K; k++)
std::cout << array[i][j][k] << ' ';
std::cout << '\n';
}
int main () {
int d[3][2][1] = { {{1}, {2}}, {{3}, {4}}, {{5}, {6}} };
foo3d(d, 3, 2, 1);
}
Pay attention to how it's called vs. how it's declared in the signature. So, why do you not need to declare the outermost size? Because only the first pointer decays, due to passing it to the function. d[0][0][0] stores element of type int, d[0][0] stores element of type int [1], d[0] stores element of type int [2][1]. Which are all themselves are arrays! Well, except d[0][0][0], obviously. So, what is the type of the array in foo3d()? It's int (*)[2][1]: pointer to array of size 2, each element of which is an array of size 1.
Parameter of a function is never an array type in C++ (nor in C).
You can declare a function that has an array parameter (as is done in the example program), but that declaration is adjusted so that the parameter is not an array as was written, but it is instead a pointer to element of such array. Example:
void f(int[]); // will be adjusted
void f(int[42]); // will be adjusted
void f(int*); // declarations above are adjusted to this
All of the above three declarations declare the same function. If the type of parameter is "array of int", then the type of the element of such array is "int" and pointer to such element is "pointer to int". Notice that the size of the array has no effect on the type of the element. As such, the size has no effect on the declaration in any way, and indeed arrays of unknown bound are allowed in parameter declaration.
Note that this adjustment occurs only in function parameters, and nowhere else. An array is not a pointer.
So, when you declare a function void setBoard(char chessboard[][cols], the parameter chessboard is not an array, because a parameter is never an array. It has been adjusted to be a pointer to element of char [][cols]. Element of such array is char[cols] i.e. array of cols number of char, therefore the adjustead parameter type is pointer to array of cols number of char i.e. char(*)[cols].
You cannot have pointer type to an array of unknown bound, so you cannot leave out cols. But you can leave out rows because as noted above, the size of the declared array parameter is ignored when the type is adjusted to be a pointer to the element of that array.
You may be wondering "if the parameter is actually not an array, then why can an array be passed as argument?". The answer is that there is another rule complementing the parameter adjustment (in simple words): Arrays implicitly convert to the pointer to element type. The result of the conversion is pointer to the first element of that array. Such conversion is called "decaying". This conversion happens automatically whenever the value of an array is used. Example:
printBoard(&chessboard[0]);
printBoard(chessboard);
The above function calls do exactly the same thing. The former explicitly passes pointer to first element, while the latter does the same thing by implicit "decay".

Need to find 3 small errors - memory bugs [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
As part of a college assignment, we were tasked with analyzing some code in an effort to identify memory issues. There's 3 we are to find. As I am quite new to the concept of pointers, I am drawing a blank. I do know main() should be returning an int and that the use of the "unsigned" means non-negative integers in this case.
Compiler Errors
Tried searching for similar problems.
void main()
{
double* d = new double;
for (unsigned int i = 0; i < 3; i++) {
d[i] = 1.5 + i;
}
for (unsigned int i = 2; i >= 0; i--) {
cout << d[i] << endl;
}
}
The program results in an infinite loop of memory addresses.
the first problem is the return type of the main function
the second one is in:
double* d = new double;
you are allocating memory for one double but in your loops, you are accessing to 3 indexes
and last
for (unsigned int i = 2; i >= 0; i--)
the unsigned type can't hold negative value and so after it gets to zero it going up again to max unsigned int (x^32)-1 and you again accessing out of range places
so your code should look like that:
#include <iostream>
int main()
{
double* d = new double[3];
for (unsigned int i = 0; i < 3; i++) {
d[i] = 1.5 + i;
}
for ( int i = 2; i >= 0; i--) {
std::cout << d[i] << std::endl;
}
delete[] d;
return 0;
}
In this statement you are creating memory in heap only for one double variable. If you need 3 . Then you must allocate memory for 3 variable like.
double* d = new double[3];
And the reason loop is infinite is because in second loop when value of i will go to -1 since the variable is unsigned it will get converted to very large positive number depending on your machine like in my machine
it get converted to 4294967295.
unsigned int i = -1;
cout<<i; //try running this code and you will see value of i to be 4294967295
Error explanation
See your 3rd and 2nd last error say the same that value is converted to very large int.
Other error said as i explained above that you have allocated memory for 1 double ie 8byte but you are using it for 3 double (d[1],d[3],d[3]) which is 8 x 3 = 24 bytes.
Remaining is return type which must be int not void

Data type clash [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
#include <iostream>
#include <iomanip>
using namespace std;
void reverseOrder (double []);
int main() {
const int size = 4;
double array[size] = {1.2, 6.7, -12.45, 34.9};
cout << "Forwards:" << " " << endl;
for (int index = 0; index < size; index++) {
cout << array[index] << endl;
}
// Display in reversed order.
cout << "Backwards: " << endl;
reverseOrder(array[size]);
return 0;
}
void reverseOrder(double array[]) {
const int size = 10;
int j;
double reverseOrder[size];
double temp = 0;
for (int i = 0, j = size - 1; i < (size / 2); i++, j--) {
temp = reverseOrder[i];
reverseOrder[i] = array[j];
reverseOrder[j] = temp;
}
for (int reverse = 0; reverse < size; reverse++) {
cout << array[reverse] << endl;
}
}
error C2664: 'void reverseOrder(double [])' : cannot convert argument 1 from 'double' to 'double []'
error is here ---> reverseOrder(array[size]);
You are calling your function reverseOrder(double[]) with array[size] as argument which is only one element of the array(*). So you are passing a double but the function expects an array.
In your case you should call the function with reverseOrder(array).
(*)in this case it is not even an element because it points to the element after the last one because the first element is accessed by 0 and so by 4 you would actually access the 5th element (thanks to drescherjm for pointing that out)
Your particular problem (just the first one from what we can observe) is that you are trying to pass a single double to a function expecting the array of doubles. It is because
array[index]
returns a value of the array associated with given index (you should call this like reverseOrder(array);). That is, it returns this as long as the index is in the allowed range. This is not the case here, because array[size] is one past the last element of the array. The last one is indexed array[size-1]. Thus you are experiencing undefined behavior.