Swapping elements in array doesn't work when using function pointer - c++

So i want to use AscendingSort() and DecendingSort() as an argument but it seems like after return the value the swap part just get skipped, hope someone explain to me, thanks!.
bool AscendingSort(int a, int b)
{
return a > b;
}
bool DecendingSort(int a, int b)
{
return a < b;
}
void SortArray(int* a, int size, bool(*func)(int, int))
{
int saveElement;
for (int x = 0; x < size; x++)
{
for (int y = x + 1; y < size; y++)
{
if (func(a[x], a[y]))
{
saveElement = a[x];
a[x] == a[y]; //Those 2 lines getting skipped.
a[y] == saveElement;
}
}
}
}
void main()
{
int a[1000];
int arrSize;
SortArray(a, arrSize, AscendingSort);
};

You probably meant to use = operator instead of ==.

Related

I keep getting the errors no match for 'operator[]', 'A', 'J' and 'N' were not declared in my code. what is the problem with it? [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 9 months ago.
Improve this question
This is the code for my matrix class
The goal here was to Complete the member functions 'void Matrix::add(const Matrix &), void Matrix::mul(double),
void Matrix::mul(const Matrix &), void Matrix::tr(void), and void Matrix::eye(int)'
of the Matrix class in the header file file matrix class
but as soon as I completed that my code started giving me errors and will not run. I am not sure what the problem is.
#ifndef MATRIX_H_
#define MATRIX_H_
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#define ROW_MAX 10
#define COL_MAX 10
// In the following, the matrix object is referred to as A,
// upper case letters denote matrices,
// and lover case letters denote scalars.
class Matrix
{
public:
Matrix(int m_, int n_, double v_) : m(m_), n(n_) { fill(v_); }; // constructor for an m_ x n_ matrix A initialized to v_
Matrix(int m_, int n_) : Matrix(m_, n_, 0.0) {} // constructor for an m_ x n_ matrix A initialized to 0.0
Matrix(int m_) : Matrix(m_, m_) {} // constructor for an m_ x m_ matrix A initialized to 0.0
Matrix() : Matrix(0) {} // constructor for a 0 x 0 matrix A (empty matrix)
Matrix(const Matrix &A_) { set(A_); } // copy constructor
void from_str(const string &str_); // reads in m, n, and the matrix elements from the string str_ in the format of "m n A[0][0] A[0][1]...A[m-1][n-1]"
string to_str(void); // returns the string representation of A in the format of "m n A[0][0] A[0][1]...A[m-1][n-1]"
int getRows(void) const; // returns the number of rows
int getCols(void) const; // returns the number of columns
double get(int i_, int j_) const; // returns A[i_][j_]
void set(int i_, int j_, double v_); // sets A[i_][j_] to v_ (A[i_][j_] = v_)
void set(const Matrix &A_); // sets A to A_ (A = A_)
void add(const Matrix &A_); // adds A_ to A (A := A + A_)
void mul(double v_); // multiplies A by the scalar v_ (A := v_ A)
void mul(const Matrix &A_); // multiplies A by A_ (A := A A_)
void tr(void); // sets A to its transpose (A := A^T)
void eye(int m_); // sets A to the m_ x m_ identity matrix (A := I)
private:
int m; // the number of rows
int n; // the number of cols
void setRows(int m_); // sets the number of rows to m_
void setCols(int n_); // sets the number of columns to n_
double data[ROW_MAX][COL_MAX]; // holds the matrix data as 2D array
void fill(double v_); // fills the matrix with v_
};
void Matrix::fill(double v_)
{
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
set(i, j, v_);
}
}
}
void Matrix::from_str(const string &str_)
{
istringstream stream(str_);
int m_ = 0, n_ = 0;
stream >> m_;
stream >> n_;
setRows(m_);
setCols(n_);
int i = 0, j = 0;
double v_;
while (stream >> v_)
{
set(i, j, v_);
j += 1;
if (j == getCols())
{
i = i + 1;
j = 0;
}
if (i == getRows())
{
break;
}
}
}
string Matrix::to_str(void)
{
ostringstream _stream("");
_stream << getRows() << " " << getCols();
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
_stream << " " << fixed << defaultfloat << get(i, j);
}
}
return _stream.str();
}
int Matrix::getRows(void) const
{
return m;
}
int Matrix::getCols(void) const
{
return n;
}
void Matrix::setRows(int m_)
{
m = m_;
}
void Matrix::setCols(int n_)
{
n = n_;
}
double Matrix::get(int i_, int j_) const
{
return data[i_][j_];
}
void Matrix::set(int i_, int j_, double v_)
{
data[i_][j_] = v_;
}
void Matrix::set(const Matrix &A_)
{
setRows(A_.getRows());
setCols(A_.getCols());
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
set(i, j, A_.get(i, j));
}
}
}
void Matrix::add(const Matrix &A_)
{
int r = getRows();
int c = getCols();
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
A_[i][j] = A_[i][j] + A_[i][j];
}
}
}
void Matrix::mul(double v_)
{
int r = getRows();
int c = getCols();
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
A[i][j] = v_ * A[i][j];
}
}
}
void Matrix::mul(const Matrix &A_)
{
int r = getRows();
int c = getCols();
int result[r][c];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
result[i][j] = 0;
for (int k = 0; k < r; k++)
{
result[i][j] += A[i][k] * A_[k][j];
}
}
}
}
void Matrix::tr(void)
{
int r = getRows();
int c = getCols();
int result[r][c];
for (int i = 0; i < N; i++)
{
for (intj = 0; j < N; j++)
{
result[i][j] = A[j][i];
}
}
}
void Matrix::eye(int m_)
{
int r = getRows();
int c = getCols();
for (int row = 0; row < m_; row++)
{
for (int col = 0; col < m_; col++)
{
if (row == col)
A[row][col] = 1;
else
A[row][col] = 0;
}
}
}
#endif
There's quite a few problems in your code. For example, in 'add', you have the following:
A_[i][j] = A_[i][j] + A_[i][j];
However, A_ is const, so you can't be modifying its data. Further, the Matrix class does not have an operator[], so you can't use A_[i] in the first place. You likely want the following:
data[i][j] = A_.data[i][j] + A_.data[i][j];
In your mul(double v_) function, you have the following line:
A[i][j] = v_ * A[i][j];
Again, there is no operator[] for your matrix, so it's not valid. Further, this function does not even have an A defined. You want to deal with the data directly.
data[i][j] = v_ * data[i][j];
In the mul(const Matrix &A_) you again have similar issues with using [], and again you have an A instead of A_. There's other issues in this function, such as not using the result after you've done the calculations.
In the tr function, you have intj instead of int j, and you're using a variable N which is not defined.
The function eye references the variable A which, again, never defined. You want data.
Using an IDE, or even an online compiler like godbolt, points out exactly where every one of these errors are. You can see here a fixed version of the code, though this doesn't fix any logic errors, just the syntax ones.

How to return a 2D array from a function in cpp

Im trying to create 2d array and want to return it tn the function... Any suggestions... I have gone through all the sites and found nothing..
double ** function() {
double array[] [] ;
/*code.............. */
return array:
;
}
It's better to use a vector like woz suggested in the comment. But with array you can do this. But first you need to be sure who create the array and it should be that same file/class that delete it. A safe way would be to dont expose the original array and get access to it by using a function (be aware that this code is not thread safe).
class Array2D
{
public:
Array2D(int xSize, int ySize)
{
xS = xSize;
yS = ySize;
arr = new double*[xSize];
for(int i = 0; i < xSize; ++i)
arr[i] = new double[ySize];
}
bool GetData(int x, int y, double& value)
{
if(x < xS && y < yS)
{
value = arr[x][y];
return true;
}
return false;
}
bool SetData(int x, int y, double value)
{
if(x < xS && y < yS)
{
arr[x][y] = value;
return true;
}
return false;
}
~Array2D()
{
for (int i = 0; i < xS; i++)
{
delete [] arr[i];
}
delete [] arr;
}
private:
//A default constructor here will prevent user to create a no initialized array
Array2D(){};
double** arr;
int xS;
int yS;
};

passing and returning vectors to a function in C++

I have a function:
void computeC(array3D fp, double& C) {
C = 0.0;
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C += fp[x][y][i];
}
}
}
}
here the variable fp and C are defined as:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
The function is a called as:
computeC(fp, C);
When I execute the main code, following error appears:
vect.cpp:9:22: error: invalid initialization of reference of type 'double&'
from expression of type 'array2D {aka std::vector<std::vector<double> >}'
and
vect.hpp:130:6: error: in passing argument 2 of 'void computeRho(array3D, double&)'
How can I solve this?
The compiler message is quite clear. The type of the second parameter that you try to pass to the function does match with the type the parameter is declared to have. The type of the parameter is double& but you try pass an array2D. array2D is not a double, so you may not pass it to the function.
To solve this, define C to be a double.
But array2D is a vector of vector of doubles. how can I again define C as double?
You can do this by removing the definition array2D C(M, array1D(N, 0)); and replacing it with double C = 0.0;
Any other idea of function definition with vectors as input and output arguments?
Yes, that's another possible approach. Instead of defining a function that takes a double& as a parameter, you could instead implement a function that does take an array2D& parameter. You could then pass C to such function.
(Edit: Answer updated after comments from OP)
Is this what you are looking for:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
double tmp = 0.0;
// Calculate sum of element in 3D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
tmp += fp[x][y][i];
}
}
}
// Update the 2D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = tmp;
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
or
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
I think that the answer of StillLearning is the best fit to your question.
Maybe you can get rid of global variables and divide that function into two more basic functionality, like sumOfElements and setElements:
#include <iostream>
#include <vector>
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
template< typename T>
double sumOfElements (T & a) {
double sum = 0.0;
for ( auto i : a) sum += sumOfElements(i);
return sum;
}
template<>
double sumOfElements<array1D> (array1D & a) {
double sum = 0.0;
for ( auto i : a) sum += i;
return sum;
}
template< typename T >
void setElements ( double val, T & a) {
for ( auto & i : a) setElements(val,i);
}
template<>
void setElements<array1D> ( double val, array1D & a) {
for ( auto & i : a) i = val;
}
int main() {
double d;
array2D b(4,array1D(5,0.1));
array3D c(3,array2D(4,array1D(5,2.0)));
d = sumOfElements(c);
std::cout << "Sum of elements: " << d << std::endl;
setElements(d,b);
std::cout << "Now all the elements of the array2D are: " << b[2][3] << std::endl;;
return 0;
}
Finally, I get the results and the functions is working perfect as desired. Thanks for the help. Working function is:
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = 0.0
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}

Checking two arrays for similar elements, returns correct values for some tests, incorrect for others

I have a function which intends to see if two arrays contain similar elements.
This is the main function:
int arr[] = {1, 2, 2};
int arrb[] = {1, 2, 1};
int a = (sizeof(arr)/sizeof(arr[0]));
int b = (sizeof(arrb)/sizeof(arrb[0]));
cout << checkForSimilar(arr,arrb,a,b);
and the following function:
int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
if (a != b) return 0; else
{
int foundSwitch = 0;
int found = 0;
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
{
if (arraya[i] == arrayb[j])
{
foundSwitch = 1;
break;
} else foundSwitch = 0;
}
}
return foundSwitch;
}
}
The function is not returning expected values, however. In the above example, for example, it should return 0, but it returns 1. This function returns the correct value for some arrays and not the correct one for others. I don't understand what I am doing wrong here.
EDIT: I worded the above function poorly. It's an equality test, where both arrays need to contain the same elements. However, they don't have to be in the same order.
The simplest and more efficient is to sort before comparing (n log n vs n²):
bool checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
std::sort(arraya, arraya + a);
std::sort(arrayb, arrayb + b);
return a == b && std::equal(arraya, arraya + a, arrayb);
}
Demo
First off the code breaks when it finds one similarity. If you want to check if both arrays have the same elements (and in the same position), you might want to change it like this:
if (a != b)
return 0;
else
{
int foundSwitch = 0;
int found = 0;
for (int i = 0; i < a; i++)
{
if (arraya[i] != arrayb[i])
{
foundSwitch = 0;
break;
}
else foundSwitch = 1;
}
return foundSwitch;
}
This code will only work if both the elements and their order are the same (ex. {3, 2, 1} and {1, 2, 3} will return 0).
You can use a for loop if you don't care about order.
if (a != b)
return 0;
else
{
int foundSwitch;
int numToCheck;
for (int i = 0; i < a; i++)
{
numToCheck = arraya[i];
foundSwitch = 0;
for (int j = 0; j < b; j++)
{
if (numToCheck == arrayb[j])
{
foundSwitch = 1;
break;
}
}
if (foundSwitch == 0)
break;
}
return foundSwitch;
}
Basically this checks the i element in arrayA. If that element is in arrayB then in breaks the inner j loop and sets found switch to 1. By default its gonna be 0 so if it goes unchanged by the time the j loop ends then you found an element that is in array a that is not in b.
your code must be:
`int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
if (a != b) return 0; else
{
int foundSwitch = 1;
int found = 0;
for (int i = 0; i < a; i++)
{
for (int j = 0; j < b; j++)
{
if (arraya[i] == arrayb[j])
{
foundSwitch = 0;
break;
}
}
if(foundSwitch == 0){
break;
}
}
return foundSwitch;
}
}`
The function you wrote says the two arrays are similar because you're simply checking if each of the elements in the first array exist in the second array. In the test example you've put here, it is the case so you're getting 1 as a return.
Since you want each element in an array to match with exactly one element of the other you should do it like this:
int foundSwitch = 0;
int found = 0;
for (int i = 0; i < a; i++)
{
for (int j = i; j < b; j++)
{
if (arraya[i] == arrayb[j])
{
foundSwitch = 1;
int temp = arrayb[i];
arrayb[i]=arrayb[j];
arrayb[j]=temp;
break;
} else foundSwitch = 0;
}
}
free[] foundvalues;
return foundSwitch;
As I commented above, you are just checking the existence of elements of one array in another one. Its would fail e.g. for [1,1,2,2] and [1,2,1,1] The simplest way would be to sort the two arrays first and then compare their elements one by one
int compare_int( const void* a, const void* b )
{
if( *(int*)a == *(int*)b ) return 0;
return *(int*)a < *(int*)b ? -1 : 1;
}
int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
if (a != b) {
return 0;
}
qsort(arraya, a, sizeof(int), compare_int); // O(n logn)
qsort(arrayb, b, sizeof(int), compare_int); // O(n logn)
for (int index = 0; index < a; ++index) { // O(n)
if (arraya[index] != arrayb[index]) {
return 0;
}
}
return 1;
}
Even complexity-wise its O(nlogn), so better than nested for loops which would be O(n2).
EDIT : Using std::sort as suggested by PaulMcKenzie
int checkForSimilar(int arraya[], int arrayb[], int a, int b)
{
if (a != b) {
return 0;
}
std::sort(std::begin(arraya), std::end(arraya));
std::sort(std::begin(arrayb), std::end(arrayb));
for (int index = 0; index < a; ++index) {
if (arraya[index] != arrayb[index]) {
return 0;
}
}
return 1;
}
A probably more efficient way is to use STL algorithms.
As an example below which copies the arrays to prevent that the originals get edited, then using std::sort to sort before checking for std::equal
bool isSimilar(int arr[], const int& size1, int arr2[], const int& size2)
{
int temp1[size1];
int temp2[size2];
copy(arr, arr + size1, temp1); // copy values into temps to avoid
copy(arr2, arr2 + size2, temp2); // editing to the originals
sort(temp1, temp1 + size1); // Sort for performance
sort(temp2, temp2 + size2);
if (equal(temp1, temp1 + size1, temp2))
return 1;
else
return 0;
}
int main()
{
int arr[] {1,2,3,4,5,6,7,8,9};
int arr2[] {9,8,7,6,5,4,3,2,1};
const int size1 = (sizeof(arr)/sizeof(*arr));
const int size2 = (sizeof(arr2)/sizeof(*arr2));
cout << (isSimilar(arr, size1, arr2, size2) ? "Similar" : "Not similar");
}
When the function returns, the original elements remain unmodified.
This code is not only is faster but it improves readability and looks more elegant.

C++ pass an array of bitfields by reference

I'm trying put my map render (console, ASCII) to one function, but it don't compile.
It should be look like this:
struct tiles {
unsigned is_visible : 1;
//...
} tile[y][x];
void render_map(const tiles (tile&)[y][x]) {
for (int i = 0; i < y; i++) {
if (tile[y].is_visible == 0) {
//...
}
}
}
int main() {
render_map(tile);
//...
}
I try to do as in this answer: C++ pass an array by reference. (const tiles (tile&)[y][x])
Thanks to all, now it's work!
struct tiles {
unsigned is_visible : 1;
//...
} tile[y][x];
void render_map(const tiles (&tile)[y][x]) {
for (int i = 0; i < y; i++) {
for (int j = 0; j < x; j++) {
if (tile[i][j].is_visible == 0) {
//...
}
}
}
}
int main() {
render_map(tile);
//...
}
And i'll think about using vector.
Sorry for such stupid question :)
You could so something like this:
struct Tiles {
unsigned is_visible : 1;
//...
};
const int x = 5;
const int y = 5;
Tiles tiles[x][y];
void render_map(const Tiles tile[x][y]) {
for (int i = 0; i < y; i++) {
if (tile[y].is_visible == 0) { // tile is a 2d array, not a 1D, thus error
//...
}
}
}
int main() {
render_map(tiles);
//...
}
However, since this is C++, I don't see why you don't use a std::vector.
Also read this answer.
With a std::vector, you could do this for example:
void print_vector(std::vector< std:: vector<Tiles> >& v) {
for(unsigned int i = 0; i < v.size(); ++i)
for(unsigned int j = 0; j < v.size(); ++j)
j += 0;
}
int main() {
std::vector< std:: vector<Tiles> >v;
v.resize(2); // make space for two vectors of tiles
Tiles t;
t.is_visible = 0;
v[0].push_back(t);
v[1].push_back(t);
print_vector(v);
return 0;
}