No matching function call for an already defined function [duplicate] - c++

This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
Closed 8 years ago.
For some reason I get the error "No matching function call to 'OptimalBinarySearchTree'" on line 15. I am not sure if it has something to do with the way I am passing the array pointers or if I have left something off. I've never tried passing a 2D array before, so it may be messing it up.
#include <iostream>
using namespace std;
void OptimalBinarySearchTree(int n, int *P[n], int (*values)[n][n], int (*roots)[n][n]);
int main()
{
const int n = 18;
char A[n] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R'};
int P[n] = {995,22,23,562,33,8,60,118,30,723,807,626,15,89,21,128,626,621};
int values[n][n];
int roots[n][n];
OptimalBinarySearchTree(n, P, values, roots);
return 0;
}
void OptimalBinarySearchTree(int n, int *P[n], int (*values)[n][n], int (*roots)[n][n])
{
for (int i = 1; i <= (n+1); i++)
{
(*values)[i][i] = 0;
}
for (int i = 1; i <= n; i++)
{
(*values)[i][i] = *P[i];
(*roots)[i][i] = i;
}
for (int d = 1; d <= (n-1); d++)
{
for (int i = 1; i <= (n-d); i++)
{
int j = i + d;
int sumP = 0;
int minValue = 999999999;
int minRoot = 0;
for (int k = i; k <= j; k++)
{
sumP += *P[k];
int value = (*values)[i][k-1] + (*values)[k+1][j];
if (value < minValue)
{
minValue = value;
minRoot = k;
}
}
(*values)[i][j] = sumP + minValue;
(*roots)[i][j] = minRoot;
}
}
};
Any help would be appreciated. Thanks,

You are adding a layer of indirection:
void OptimalBinarySearchTree(int n, int *P[n], int (*values)[n][n], int (*roots)[n][n]);
int main()
{
const int n = 18;
char A[n] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R'};
int P[n] = {995,22,23,562,33,8,60,118,30,723,807,626,15,89,21,128,626,621};
int values[n][n];
int roots[n][n];
OptimalBinarySearchTree(n, P, values, roots);
return 0;
}
The int *P[n] and int (*values)[n][n], etc means that your function takes an array of int pointers (P) and a two dimensional array of int pointers (called values). But you are passing an array of int values and a two-dimensional array of int values.
Remove the * and it should get better. However, I'm pretty sure it's either completely illegal or a compiler extension to pass int n and then use it for the dimensions of your values array. Since it's C++, you may want to consider using vector<int> and vector <vector <int> > instead.

Related

C++ syntax difference: 2D- and 1D-arrays (pointer arithmetic)

Problem
I am learning C++, and am writing code to transpose a 2D array and to reverse a 1D-array.
Please look at the invocations. Why do I have to use reverse(arr, 4) for reverse, whereas I have to use transpose(*in_matrix, *out_matrix) for transpose?
There are two ways of writing each function signature. Both seem to give the same results.
Thank you.
EDIT: I know how to solve it with array-subscript. I am doing it this way deliberately for practice. Now I understand there's no point trying this. However, I have added some notes summarised from the answers below.
Code
#include <iostream>
using namespace std;
const int LENGTH = 2;
const int WIDTH = 3;
void printArray(const int arr[], const int N) {
cout << arr[0];
for (int i = 1; i < N; ++i) {
cout << ", " << arr[i];
}
cout << "\n";
}
// void transpose(int* const input, int* const output) { // both these signatures
void transpose(const int input[], int output[]) { // works (I find the top one clearer)
for (int i = 0; i < WIDTH; ++i) {
for (int j = 0; j < LENGTH; ++j) {
*(output + j * WIDTH + i) = *(input + i * LENGTH + j);
}
}
}
// void reverse(int arr[], const int N) { // both these signatures
void reverse(int* arr, const int N) { // works (I prefer this one)
for (int i = 0; i < N / 2; ++i) {
int temp = *(arr + i);
*(arr + i) = *(arr + N - 1 - i);
*(arr + N - 1 - i) = temp;
}
}
int main() {
int arr[4] = {2,4,6,8};
printArray(arr, 4);
reverse(arr, 4); // this works
// reverse(*arr, 4); // this doesn't work
printArray(arr, 4);
int in_matrix[WIDTH][LENGTH];
in_matrix[0][0] = 1;
in_matrix[0][1] = 2;
in_matrix[1][0] = 3;
in_matrix[1][1] = 4;
in_matrix[2][0] = 5;
in_matrix[2][1] = 6;
int out_matrix[LENGTH][WIDTH];
// transpose(in_matrix, out_matrix); // this doesn't work
transpose(*in_matrix, *out_matrix); // this works
cout << "in_matrix is:\n";
for (int i = 0; i < WIDTH; ++i) {
printArray(in_matrix[i], LENGTH);
}
cout << "out_matrix is:\n";
for (int i = 0; i < LENGTH; ++i) {
printArray(out_matrix[i], WIDTH);
}
return 0;
}
Summary of answers
LESSON: DO NOT USE pointer-arithmetic for 2D-arrays
decay
KEY IDEA: arr -----> &arr[0] type int*
This is also the reason the two function signatures are equivalent.
// transpose(int* const input, int* const output) // alt.
Signature: transpose(const int input[], int output[])
i.e. it expects an array of ints (or equiv., a pointer to an int)
(id)
IDENTITY: a[i] = *(a + i) ALWAYS TRUE
Reason transpose(in_matrix, out_matrix) doesn't work:
decay
out_matrix -----> &out_matrix[0] type int(*)[WIDTH]
Reason transpose(*in_matrix, *out_matrix) works:
(id) decay
*out_matrix = out_matrix[0] -----> &(out_matrix[0])[0]
In C, arrays and pointers are a bit intricately mixed up. An array can be considered as a pointer with some 'size' information attached to it (that is not stored anywhere, but the compiler knows). Hence, sizeof when used on an array gives you the size of the contents of the entire array, while on a pointer, it gives the size of the pointer.
When you pass an array to a function, the size information is lost - in effect, the array decays to a pointer. For most practical purposes, a pointer to a type can be used exactly like a one-dimensional array of that type. The array subscript notation ([]) can also be used to access consecutive elements using a pointer.
However, with 2D arrays, this gets more complicated. 2D arrays and double pointers may use the same access syntax of the form a[i][j] but they are not interchangeable. A 2D array decays to a pointer to an array while a double pointer is a pointer to a pointer.
Coming back to your question, the two ways of writing the function signatures are essentially equivalent because 1D arrays decay to pointers when passed to functions. So void reverse(int* arr, const int N) is the same as void reverse(int arr[], const int N).
In your transpose function however, you are passing a 2D array. It would decay to a pointer to an array. But in your function declaration, you are accepting these arguments as arrays (or in effect, pointers). This still works fine because of the quirks of C. A 2D array can be also treated as one big 1D array with the rows laid out consecutively one after the other. It is, however, not the best approach. This also reflects in the fact that you had to de-reference the array names when you passed them to the transpose function, because it expects a 1D array (or a pointer) and not a 2D array (or a pointer to an array).
Also, C/C++ provides a much more elegant way to access arrays than using unwieldy pointer arithmetic. So the following approach is what I would recommend. It should work exactly like the code you originally posted, but would be cleaner and more readable.
#include <iostream>
using namespace std;
const int LENGTH = 2;
const int WIDTH = 3;
void printArray(const int arr[], const int N) {
cout << arr[0];
for (int i = 1; i < N; ++i) {
cout << ", " << arr[i];
}
cout << "\n";
}
void transpose(const int input[][LENGTH], int output[][WIDTH]) {
for (int i = 0; i < WIDTH; ++i) {
for (int j = 0; j < LENGTH; ++j) {
output[j][i] = input[i][j];
}
}
}
void reverse(int* arr, const int N) {
for (int i = 0; i < N / 2; ++i) {
int temp = arr[i];
arr[i] = arr[N - 1 - i];
arr[N - 1 - i] = temp;
}
}
int main() {
int arr[4] = {2,4,6,8};
printArray(arr, 4);
reverse(arr, 4);
printArray(arr, 4);
int in_matrix[WIDTH][LENGTH];
in_matrix[0][0] = 1;
in_matrix[0][1] = 2;
in_matrix[1][0] = 3;
in_matrix[1][1] = 4;
in_matrix[2][0] = 5;
in_matrix[2][1] = 6;
int out_matrix[LENGTH][WIDTH];
transpose(in_matrix, out_matrix);
cout << "in_matrix is:\n";
for (int i = 0; i < WIDTH; ++i) {
printArray(in_matrix[i], LENGTH);
}
cout << "out_matrix is:\n";
for (int i = 0; i < LENGTH; ++i) {
printArray(out_matrix[i], WIDTH);
}
return 0;
}

Extract pair numbers from array

Good evening, folks.
I'm currently experiencing difficulties with extracting pair numbers from an array. I have the following code:
#include <iostream>
using namespace std;
int *paire(int *d, int length) {
int counter = 0;
int position = 0;
for (int i=0; i<length; i++) {
if (d[i] % 2 ==0)
counter++;
}
int *k = new int[counter];
for (int i=0; i<length; i++) {
if (d[i] % 2 ==0) {
k[position] = d[i];
position++;
}
}
return k;
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int *array1 = paire(b,8);
for (int i=0; i<5; i++) { // how can I point here to the counter in paire() ?
cout<<array1[i];
}
delete[] array1;
return 0;
}
So I think I've got it right with initializing the new array in function paire, but I'm having difficulties to iterate through the array.
P.S. I'm first year in university, so I would really be thankful if you can keep the same simplicity in the answers. Thanks in advance!
It appears that you need to return 2 separate values: the number of even numbers in the array b, and the address of the newly allocated memory that is storing exclusively those even numbers.
Since you can not return multiple variables, one solution that does minimal modification to your code would be as follows.
int *paire(int *d, int length, int& counter) {
counter = 0;
// rest of your function remains unchanged
// ...
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int evenNumbers;
int *array1 = paire(b,8, evenNumbers);
for (int i=0; i<evenNumbers; i++) {
cout<<array1[i];
}
delete [] array1;
return 0;
}
Alternatively, you can return the value in counter and send the reference to the int* variable as an argument to paire function. Or, you can declare paire to have return type void and use references to pass back both the values.
You can further simplify your function by allocating to that of the length and returning the counter by an output parameter.
#include <iostream>
using namespace std;
int *paire(int *d, int length, int &counter) {
counter = 0;
int *k = new int[length]; // allocate for the maximum memory
for (int i = 0; i < length; ++i) {
if (d[i] % 2 == 0) {
k[counter++] = d[i];
}
}
return k;
}
int main() {
int b[8] = {1,2,3,4,5,6,7,8};
int counter = 0;
int *array1 = paire(b,8, counter);
for (int i=0; i<counter; i++) { // how can I point here to the counter in paire() ?
cout<<array1[i] << " ";
}
delete [] array1;
return 0;
}
But please note that as others have already pointed out this method is quite error prone in the sense that it leaves the responsibility to the client to delete the internal memory used by paire function.

C++ parameterized constructor makes code to stop working when large input's are passed

void initialize(int arr[], int size[], int n)
{
int i;
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
}
class hell
{
public:
int edges;
int vertices;
pair<int , pair<int,int>> p[100000];
int disjoint_set[10000];
int cc_size[10000]; // size of connected components
hell(int e, int v)
{
edges = e;
vertices = v;
initialize(disjoint_set, cc_size, vertices);
}
};
In the following class when I create an object using vertices=100000 and edges=100000, the code stops working. But when we remove the initialize(disjoint_set, cc_size, vertices) it starts working. I don't have any clue to such behavior. Please guide me.
Arrays in C++ are zero indexed, which means that valid index is in [0..n[ range. Your code does it wrong:
for(i = 1; i <= n; i++) {
arr[i] = i;
size[i] = 1;
}
it should be:
for(i = 0; i < n; i++) {
arr[i] = i + 1;
size[i] = 1 + 1;
}
or better use algo std::iota() and std::fill():
std::iota( arr, arr + n, 1 );
std::fill( size, size + n, 1 );
and you better use std::vector, which will adjust its size properly, rather than have huge array.

Vector of vectors initialization work won't but a matrix array does, why so? [duplicate]

This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 6 years ago.
So I'm practicing solving DP problems and found out this issue I couldn't comprehend why. If I initialize my vector of vectors with size n, operations won't work. Meanwhile if I just declare cost as int cost[n][n] it does. Please tell me why.
int sum (vector<int> freq, int i, int j){
int s=0;
for (int x=i; x<=j; x++) {
s+=freq[x];
}
return s;
}
int optimalSearchTree(vector<int> keys, vector<int> freq){
int n = keys.size();
vector<vector<int>> cost( n,vector<int>( n,0 )) ;
for (int i = 0; i < n; i++) {
cost[i][i] = keys[i];
}
for (int L=2; L<=n; L++) {
for (int i = 0; i<= n-L+1; i++) {
int j = i+L-1;
cost[i][j] = INT_MAX;
for (int r=i; r<=j; r++) {
int c = ((r > i)? cost[i][r-1]:0) +
((r < j)? cost[r+1][j]:0) +
sum(freq, i, j);
if (c < cost[i][j]) {
cost[i][j] = c;
}
}
}
}
return cost[0][n-1];
}
int main(){
vector<int> keys = {10,12,16,21};
vector<int> freq = {4,2,6,3};
cout<<optimalSearchTree(keys, freq)<<endl;
// int n = keys.size();
//vector<vector<int>> cost( n,vector<int>( n,0 )) ;
//cout<<cost.size()<<" "<<cost[0].size()<<endl;
}
I believe the solution follows the same as this question:
Accessing an array out of bounds gives no error, why?
In it, specifies that out of bound access from a int arr[n][n] won't return any error. Meanwhile accessing out of bound positions from a vector will.

C++ Merging 2 sorted arrays into 1 sorted

So I am trying so merge 2 sorted arrays into one and I get really weird numbers like an output. Here is my code:
#include<iostream>
using namespace std;
int* add(int first[],int second[], int sizeFirst, int sizeSecond)
{
int result[sizeFirst + sizeSecond];
int indexFirst = 0,indexSecond = 0;
for(int i = 0;i < sizeFirst + sizeSecond;i++)
{
if(indexFirst == sizeFirst || first[indexFirst] > second[indexSecond])
{
result[i] = second[indexSecond];
indexSecond++;
}
else
{
result[i] = first[indexFirst];
indexFirst++;
}
}
return result;
}
int main()
{
int n;
cin>>n;
int arr[n];
for(int i = 0;i < n;i ++)
cin>>arr[i];
int m;
cin>>m;
int arr2[m];
for(int i = 0;i < m;i ++)
cin>>arr2[i];
int *res;
res = add(arr,arr2,n,m);
for(int i = 0;i < n + m;i ++)
cout<<res[i]<<" ";
return 0;
}
Notes: It sorts it properly, so the mistake is not there. Also I need to do it as a function because I will need it later on for some other stuff.
return result;
You are returning a pointer to local array, which gets destroyed immediately after - this is undefined behavior. You should either allocate it using new or use std::vector (which is preferred).
Also, int result[sizeFirst + sizeSecond]; is not valid C++ because the standard doesn't allow variable sized arrays (but int* result = new int[sizeFirst + sizeSecond]; is valid).