C++ Pointers to functions - c++

using namespace std;
int addition (int a, int b)
{
return (a+b);
}
int subtraction (int a, int b)
{
return (a-b);
}
int operation (int x, int y, int (*functocall)(int,int))
{
int g;
g = (*functocall)(x,y);
return(g);
}
int main()
{
int m,n;
int (*minus)(int,int) = subtraction;
m = operation (7,5,addition);
n = operation (20,m,minus);
cout << n;
return 0;
}
Can anybody explain this line for me
int (*minus)(int,int) = subtraction;
Thanks a lot!

int (*minus)(int,int) = subtraction; is creating a variable called minus and assigning it a pointer to the function called subtraction. if the code is valid then the function subtraction would be declared int subtraction(int a, int b);.
the best way to deal with function pointers is to make them readable using typedef.
example:
typedef int (*math_op)(int,int); // new types is math_op
int subtraction (int a, int b)
{
return (a-b);
}
math_op minus = subtraction;
later on these can be called like they are normal functions.
example:
int result = minus(10, 2); // result is now set to 8
your code rewritten:
using namespace std;
typedef int (*math_op)(int,int); // new types is math_op
int addition (int a, int b)
{
return (a+b);
}
int subtraction (int a, int b)
{
return (a-b);
}
int operation (int x, int y, math_op functocall)
{
int g;
g = functocall(x,y);
return(g);
}
int main()
{
int m,n;
math_op minus = subtraction;
m = operation (7,5,addition);
n = operation (20,m,minus);
cout << n;
return 0;
}

"minus" is a name of a variable which is a pointer to a function taking two int arguments and returning another int.
The function called "operation" takes 3 arguments: 2 ints and a pointer to a function which operates on 2 ints and return another one. When invoked, the operation function applies argument 3 to the arguments 1 and 2.

int (*minus)(int,int)
says
A pointer to a function taking two ints as arguments returning an int.
The parentheses around (*minus) are there to make sure that the asterisk binds to the name of the typedef and not the return type (i.e., the function does not return an int*).

Related

Data in int* argument of function not returned caller

Compiled with g++ on WSL2, sample output of
#include <stdlib.h>
#include <stdio.h>
#include <vector>
using std::vector;
vector <int> powers_2(const int npow) {
vector <int> v;
int j = 2;
for (int i=0; i<npow; i++) {
v.push_back(j);
j*= 2;
}
return v;
}
void pow_2(const int npow, int *v, int *nv) {
vector <int> w = powers_2(npow);
*nv = w.size();
v = (int*)malloc(*nv * sizeof(int));
for (int i=0; i<*nv; i++) {
v[i] = w[i];
printf("%d %d %d\n",i,v[i],w[i]);
}
}
int main() {
int *y;
int ny;
pow_2(3,y,&ny);
printf("\n in main\n");
for (int i=0; i<ny; i++) {
printf("%d %d\n",i,y[i]);
}
}
is
0 2 2
1 4 4
2 8 8
in main
0 1
1 0
2 1091723517
So the argument int* v is set in pow_2, but the data is not returned to caller. Why?
There is a difference between passing function arguments by value, by pointer and by reference.
The line
pow_2(3,y,&ny);
will pass the value of y to the function pow_2, which means that a copy of the value of the variable y will be made, which will exist as the local variable v in the function pow_2. This is not what you want, because changing the variable v in the function pow_2 will only change that variable, but it won't change the value of the original variable y in the function main.
What you instead want is to pass the variable y itself to the function pow_2, not its value, so that it can be changed by the function pow_2. There are two ways of doing this. You can pass the variable y
as a reference, or
as a pointer
to the function pow_2.
To make the function pow_2 take a reference to an int * instead of the value of an int *, you can change the line
void pow_2(const int npow, int *v, int *nv) {
to:
void pow_2(const int npow, int * &v, int *nv) {
Alternatively, you can make the function pow_2 take a pointer to an int * instead of the value of an int *. You can change the line
void pow_2(const int npow, int *v, int *nv) {
to
void pow_2(const int npow, int **v, int *nv) {
However, this will require you to rewrite the function pow_2 so that the pointer is deferenced whenever it is used:
void pow_2(const int npow, int **v, int *nv) {
vector <int> w = powers_2(npow);
*nv = w.size();
*v = (int*)malloc(*nv * sizeof(int));
for (int i=0; i<*nv; i++) {
(*v)[i] = w[i];
printf("%d %d %d\n",i,(*v)[i],w[i]);
}
}
Also, you will have to call the function differently. You will have to change the line
pow_2(3,y,&ny);
to:
pow_2(3,&y,&ny);
Therefore, passing the variable as a reference is easier than passing it as a pointer.

How do I add numbers in C++ again?

Seriously, I don’t remember..
Would an integer work??
But I don’t know why its not working...
I'm trying to add integers, like this.
int main() {
i = 1;
b = 3;
}
Signed int addition() {
i + b
}
You can't use functions and variables, including local variables, parameters, etc before they have been declared first. Though, you can initialize variables at the same time you declare them. For example:
#include <iostream>
int addition(int a, int b);
int main() {
int i = 1;
int b = 3;
int sum = addition(i, b);
std::cout << sum;
}
int addition(int a, int b) {
return a + b;
}
You have a lot of syntax errors in that code. Until you are more comfortable with programming, just start with a simple working "Hello world" example, and add one line of code at a time, compiling after each line you add. Look carefully at the error messages the compiler gives you and fix them before adding another line. You might arrive at something like this:
int main() {
int i = 1;
int b = 3;
return i + b;
}
When you run this and check the process return code (e.g. using$? in Bash) then you would get 4.
It should not be hard.
// [...]
int Add(int x, int y) { return x + y; }
using namespace std;
int main(void) {
int a = 1, b = 2;
printf("%d\n", Add(a + b));
return 0;
}

Problem with a class setter function. Class setter function does not assign values properly

the statement below the function calling is not executed. i am at a loss, why this is so? could someone please clarify. Please consider the code below :
#include<iostream>
#include<cmath>
using namespace std;
class Matrix
{
private:
int row,col;
double *values;
public:
Matrix();
Matrix(int r, int c, double* x);
void setdim(int m, int n){row=m;col=n;}
int getrowdim() const {return row;}
int getcoldim() const {return col;}
void set_values(int i, double x);
double get_value(int i) const;
friend Matrix operator+(const Matrix &A, const Matrix &B);
};
Matrix::Matrix()
{
this->row = 0;
this->col = 0;
this->values = NULL;
}
Matrix::Matrix(int r, int c, double* x)
{
this->row = r;
this->col = c;
this->values = new double[r*c];
for (int i =0;i<r*c;i++)
{
cout<<"Enter value ["<<i<<"] ";
cin>>this->values[i];
}
}
void Matrix::set_values(int k, double x)
{
this->values[k] = x;
}
Matrix operator+(const Matrix &A, const Matrix &B)
{
int rowa = A.getrowdim();
int cola = A.getcoldim();
int rowb = B.getrowdim();
int colb = B.getcoldim();
if(rowa == rowb && cola == colb)
{
Matrix C;
C.setdim(rowa, colb);
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m );
cout<<"Returned from C.set_values()"<<endl;
// THIS STATEMENT DOES NOT GET PRINTED. PLEASE TELL THE REASON // WHY. I SUSPECT THE ERROR IS HERE
}
return C;
}
else
{
cout<<"Invalid Operation";
return A;
}
}
double Matrix::get_value(int i) const
{
return this->values[i];
}
int main()
{
Matrix A(2,2,NULL);
Matrix B(2,2,NULL);
Matrix C;
C = A+B;
return 0;
}
The statement - Returned from C.set_values() does not get printed at all .
Could someone help clarify why this is the case? Thanks a lot for the help!
Here:
Matrix C; // (1)
C.setdim(rowa, colb); // (2)
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m ); // (3)
You default construct a Matrix (1). The default constructor just sets the member values to NULL. Then you adjust the size members in (2), but values is still NULL. Then, in (3) you call set_values which tries to access array elements, but there is no array.
The problem is that your Matrix has a raw owning pointer as member. When a class manages a resource you must follow the rule of 3/5. If you don't, the class is broken. Managing a resource is not trivial, and following the rule of 3/5 is just the bare minimum.
The simpler alternative that you should strive for is the rule of 0. For a class that does not manage a resource, the compiler generated special members are just right. If you replace the raw pointer member with a std::vector<double> then you do not need to worry about copying, assignment or destruction, because the compiler will generate the required methods for you.

Returning a multidimensional array in C++

void createArray(int a, int b, int c, int d, int array[3][3]){
int state[3][3];
for(int x=0;x<3;x++){
for(int y=0;y<3;y++){
if(x == a && y == b){
state[x][y] = array[c][d];
}
else if(x == c && y == d){
state[x][y] = array[a][b];
}
else{
state[x][y] = array[x][y];
}
}
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout << state[i][j] << " ";
}
cout << endl;
}
}
I have basically got this function which clones the multidimensional array that is inputed but swaps the values of the two co-ordinates (a,b) and (c,d) around. This is then outputted out to the console.
However what I would really like is for this to be returned as a multidimensional array, but I don't think this can be done?
I have looked at vectors and pointers but don't really understand them and if I use them, I will then have to change all the previous code I have written.
There are multiple options.
Option 1 - pass the array to the function
void createArray(int a, int b, int c, int d, const int array[3][3], int outArray[3][3]){
...
}
Option 2 - return a reference to an array - just make sure the array does not live on the stack of the function it's returned from.
typedef int My3Times3Array[3][3];
const My3Times3Array& createArray(int a, int b, int c, int d, const int array[3][3]){
...
}
Option 3 - return a class that contains an array
struct Array
{
int array[3][3];
};
...
Array createArray(int a, int b, int c, int d, const int array[3][3]){
...
}
There's also std::vector, std::array, or boost::matrix, but since you mentioned you aren't comfortable with pointers yet, I'd save template classes for later.
When you want to return a non conventional data type (int, char etc), the best way of doing it is by making your very own one.
struct mat3
{
int myArray[3][3];
};
mat3 createArray(int a, int b, int c, int d, int array[3][3]){
mat3 state;
for(int x=0;x<3;x++){
for(int y=0;y<3;y++){
if(x == a && y == b){
state.myArray[x][y] = array[c][d];
}
else if(x == c && y == d){
state.myArray[x][y] = array[a][b];
}
else{
state.myArray[x][y] = array[x][y];
}
}
}
for(int i=0;i<3;i++){
for(int j=0;j<3;j++){
cout << state.myArray[i][j] << " ";
}
cout << endl;
return state;
}
}
I have looked at vectors and pointers but don't really understand them and if I use them, I will then have to change all the previous code I have written
I suggest you study pointers further, they are so essential that you are already using them without knowing it.
You can dynamically allocate a two-dimensional array and return pointer to it. For example
typedef int ( *STATE )[3];
STATE createArray(int a, int b, int c, int d, int array[3][3]){
STATE state = new int[3][3];
//...
return state;
}
Or
int ( *createArray(int a, int b, int c, int d, int array[3][3] ) )[3]{
int ( * state )[3] = new int[3][3];
//...
return state;
}
In fact the same result you can get if you will use vectors. For example
#include <vector>
#include <array>
//...
std::vector<std::array<int, 3>> createArray(int a, int b, int c, int d, int array[3][3]){
std::vector<std::array<int, 3>> state( 3 );
//...
return state;
}

Curious as to why my constructors don't seem to be working

The following is how I was taught to use constructors, and it seems to work for one variable, but when I use a few it seems to act odd.
I'm not too sure what to do to fix this, but I would like some direction. Thanks in advance!
#include <iostream>
#include <string>
using namespace std;
class Numbers
{
public:
Numbers (int a, int b, int c)
{
setNum (a);
setNum (b);
setNum (c);
}
void setNum (int x, int y, int z)
{
numbers = x;
digits = y;
numerals = z;
}
int getNum ()
{
return numbers;
return digits;
return numerals;
}
int add (int x, int y, int z)
{
int answer = x + y + z;
return answer;
}
private:
int numbers;
int digits;
int numerals;
};
int main ()
{
Numbers numbersobject (12,13,14);
cout << numbersobject.getNum () << endl;
return 0;
}
Odd meaning compile error?!
In the constructor, look at your setNum, it must take 3 parameters. You probably need
setNum(a,b,c);
And you CANNOT return 3 elements in getNum, using 3 return statements. If you need to return more than 2 elements, use std::tuple, or std::pair for 2 elements.
You could change your constructor to use a member initialization list
Numbers (int a, int b, int c)
: numbers {a}, digits {b}, numerals {c} {}
Or the older version
Numbers (int a, int b, int c)
{
numbers = a;
digits = b;
numerals = c;
}
I suggest you simplify your constructor
class Numbers
{
public:
Numbers(int a, int b, int c)
: numbers(a), digits(b), numerals(c) // Initialization list
{ ; }
//...
};
In your simple class, there is no need for the constructor to call a setter function.