function pointers: trying to pass a function as an argument

Pages: 12
Hello, my program works ok when I pass to the function simpson all four parameters as doubles and ints, but because I need the last parameter to be passed as a function, I get errors. I have written problem_13.cpp and simpson.h programs. I think I understand pointer functions, but they seem to not work for me. The errors I get are from these lines:
f = simpson(a,b,n,function(fk_1)); from problem_13.cpp line 26
f = simpson(a,b,n,function(fk_2)); from problem_13.cpp line 31
double simpson(double a, double b, int n, double function); from simpson.h file line 8
if (function(fk_1) == true); from simpson.h file line 12
if (function(fk_2) == true); from simpson.h file line 20

Please help me to understand how to solve these errors and make a function passed as a parameter to simpson() where I need the 4th parameter to be fk_1() or fk_2(). Looking forward to all responses.

problem_13.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <iostream>
#include <cmath>
#include <cstdlib>
#include "simpson.h"

void text();

int main()
{
double a, b, f;
int n, m;

printf("a = "); // choose the interval start
scanf("%lf", &a);
printf("b = "); // choose the interval end
scanf("%lf", &b);
printf("n = "); // choose how many steps
scanf("%d", &n);
printf("\n");

  text(); // show the menu
  scanf("%d", &m); // choose which function from text() to integrate
  switch (m)
  {
    case 1:
      f = simpson(a,b,n,fk_1); // should calculate the integral of the first function
      printf("Integral = %3.3f \n", f); // should give the integral of the first function
      break;

    case 2:
      f = simpson(a,b,n,fk_2); // should calculate the integral of the second function
      printf("Integral = %3.3f \n", f); // should give the integral of the second function
      break;

    case 3:
    printf("Quiting...\n"); // quits the program
    return 0;
    break;

    default:
    printf("Incorrect choices.\n"); // if pressed anything ecept 1,2 or 3 gives a menu text again
    text();
    break;
  }
}

void text()
{
  printf("Meniu\r\n\n");
  printf("Which function to integrate?\n");
  printf("f(x) = x - press 1\n");
  printf("f(x) = x^2 - press 2\n");
  printf("Leave menu - press 3\n");
  printf(": ");
}


simpson.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <cmath>

double function(double, double (*f)(double));
double fk_1(double);
double fk_2(double);

double simpson(double a, double b, int n, double function);
{
  double sum = 0.0; // base length 
  double h2 = h / 2; // half base length
    if (function(fk_1) ==  true)
    {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h; // left side of the simpson's rule to calculate integral of a function
    sum += fk_1(left) + 4 * fk_1(left + h2) + fk_1(left + h); // remaining stes of the simpson's rule to calculate the integral of a function
    }
    }
    else if (function(fk_2) == true) {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h; // look above
    sum += fk_2(left) + 4 * fk_2(left + h2) + fk_2(left + h); // look above
    }
    }
  // integral calculation
  return h / 6 * sum;
}

double function(double x, double (*f)(double))
{
  return (*f)(x);
}

double fk_1(double x)
{
  return x;
}

double fk_2(double x)
{
  return (x * x);
}


P.S. If you need more information - let me know and I'll provide. Also any reading material suggestions are welcome.
Last edited on
I presume that the syntax is something like in this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
double foo(double, double, double (*)(double) );
double bar(double);

int main()
{
  double a{}, b{};
  auto f = foo( a, b, bar );
}

double foo( double h, double k, double (*fun)(double) )
{
  return fun( h * k );
}

double bar( double x ){
  return x;
}
Thanks. I've done what you have suggested, but am getting a new error now:
1
2
3
4
5
pratimas_13.cpp:26:11: error: no matching function for call to 'simpson'
      f = simpson(a,b,n,fk_1);
./simpson.h:8:8: note: candidate function not viable: no known conversion from
      'double (double)' to 'double' for 4th argument
double simpson(double a, double b, int n, double function);

What might be wrong?
Also what should I write in the simpson funtion? Now it is double simpson(double a, double b, int n, double function); Would that be ok, but it doesn't work?

As per your suggestions I have done exactly the syntax you mentioned and fixed the code above, but have it still not working :(
Last edited on
What can you tell about these functions? Where do they differ?
1
2
double foo( double, double, int, double );
double foo( double, double, int, double (*)(double) );
The second is the pointer to function. However I don't know how to explain the first one. Could you elaborate on it?
Also in the same post, but under Begginers forum, I had a question whether I can add simpson function to my source.cpp file. However, I can't. My problem says that simpson function has to be written outside the source .cpp file and in .cpp it should be included and called onto.

The errors I get at the moment are:
1
2
3
4
5
6
7
8
./simpson.h:8:43: error: C++ requires a type specifier for all declarations
double simpson(double a, double b, int n, function(double, double (*f)(d...
./simpson.h:9:1: error: expected unqualified-id
./simpson.h:8:62: error: expected function body after function declarator
double simpson(double a, double b, int n, double &function()));
pratimas_13.cpp:26:11: error: use of undeclared identifier 'simpson'
      s = simpson(a,b,n,fk_1);
{


Perhaps I need to include not a header file, but something else like .obj or .lib file to not get the error of undeclared identifier simpson?
Last edited on
The first foo() is a function that returns a double value and requires four arguments.
The types of arguments are double, double, int, and double.

The second foo() is a function that returns a double value and requires four arguments.
The types of first three arguments are double, double, and int, just like in the first foo().
The fourth argument must be a function that requires one double argument and returns a double.


My problem says that ...

Sounds like you should practice splitting your program into multiple source files.
This should help: http://www.cplusplus.com/articles/Gw6AC542/



1
2
3
4
double simpson( double a, double b, int n, double function ) ;   // error
{
  // code
}

Semicolon (;) should not be there.


PS.
1
2
3
4
5
6
int foo(double); // name 'foo' means a function here

void bar( std::string foo )
{
  // name "foo" is a string variable here
}

While same name can be reused for different things in different scopes, it is very confusing.
Last edited on
Thank you for explaining keskiverto. I'll read your proposed help and will post again if I figure something out :)

When I change simpson function to double simpson(double a, double b, int n, double function(double (*f)(double))); I get these errors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
./simpson.h:9:1: error: expected unqualified-id
{
^
pratimas_13.cpp:26:11: error: no matching function for call to 'simpson'
      s = simpson(a,b,n,fk_1);
          ^~~~~~~
./simpson.h:8:8: note: candidate function not viable: no known conversion from
      'double (double)' to 'double (*)(double (*)(double))' for 4th argument
double simpson(double a, double b, int n, double function(double (*f)(double)));
       ^
pratimas_13.cpp:31:11: error: no matching function for call to 'simpson'
      s = simpson(a,b,n,fk_2);
          ^~~~~~~
./simpson.h:8:8: note: candidate function not viable: no known conversion from
      'double (double)' to 'double (*)(double (*)(double))' for 4th argument
double simpson(double a, double b, int n, double function(double (*f)(double)));
       ^
3 errors generated.
Last edited on
One can create simpler aliases for complex typenames:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using Func = double (*)(double);
double foo(double, double, Func );
double bar(double);

int main()
{
  double a{}, b{};
  auto f = foo( a, b, bar );
}

double foo( double h, double k, Func fun )
{
  return fun( h * k );
}

double bar( double x ){
  return x;
}
I've seperated the program into three files:

function_header.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cmath>

using Func = double (*)(double);

double function(double x, Func f)
{
  return f(x);
}

double fk_1(double x)
{
  return x;
}

double fk_2(double x)
{
  return (x * x);
}

simpson.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <cmath>

double simpson(double a, double b, int n, Func);
{
  double sum = 0.0; 
  double h = (b - a) / n; // base length
  double h2 = h / 2; // half base length
    if (function(fk_1) ==  true)
    {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h;
    sum += fk_1(left) + 4 * fk_1(left + h2) + fk_1(left + h);
    }
    }
    else if (function(fk_2) == true) {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h;
    sum += fk_2(left) + 4 * fk_2(left + h2) + fk_2(left + h);
    }
    }
  return h / 6 * sum;   // integral calculation
}

pratimas_13.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <cmath>
#include <cstdlib>
#include "function_header.h"
#include "simpson.h"

void text();

int main()
{
double a, b, f;
int n, m;

printf("a = "); // choose the interval start
scanf("%lf", &a);
printf("b = "); // choose the interval end
scanf("%lf", &b);
printf("n = "); // choose how many steps
scanf("%d", &n);
printf("\n");

  text(); // show the menu
  scanf("%d", &m); // choose which function from text() to integrate
  switch (m)
  {
    case 1:
      f = simpson(a,b,n,fk_1); // should calculate the integral of the first function
      printf("Integral = %3.3f \n", f); // should give the integral of the first function
      break;

    case 2:
      f = simpson(a,b,n,fk_2); // should calculate the integral of the second function
      printf("Integral = %3.3f \n", f); // should give the integral of the second function
      break;

    case 3:
    printf("Quiting...\n"); // quits the program
    return 0;
    break;

    default:
    printf("Incorrect choices.\n"); // if pressed anything except 1,2 or 3 gives a menu text again
    text();
    break;
  }
}

void text()
{
  printf("Meniu\r\n\n");
  printf("Which function to integrate?\n");
  printf("f(x) = x - press 1\n");
  printf("f(x) = x^2 - press 2\n");
  printf("Leave menu - press 3\n");
  printf(": ");
}


However, I get errors from function_header.h file. I believe everything should be correct. I've taken your idea and wrote aliases as depicted above.
Here are the errors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
In file included from pratimas_13.cpp:5:
In file included from ./simpson.h:3:
./function_header.h:6:8: error: redefinition of 'function'
double function(double x, Func f)
       ^
./function_header.h:6:8: note: previous definition is here
double function(double x, Func f)
       ^
In file included from pratimas_13.cpp:5:
In file included from ./simpson.h:3:
./function_header.h:11:8: error: redefinition of 'fk_1'
double fk_1(double x)
       ^
./function_header.h:11:8: note: previous definition is here
double fk_1(double x)
       ^
In file included from pratimas_13.cpp:5:
In file included from ./simpson.h:3:
./function_header.h:16:8: error: redefinition of 'fk_2'
double fk_2(double x)
       ^
./function_header.h:16:8: note: previous definition is here
double fk_2(double x)
       ^
In file included from pratimas_13.cpp:5:
./simpson.h:6:1: error: expected unqualified-id
{
^


Where I might be doing it wrong?
Last edited on
I understod the error: I included function_header.h two times. Thus I removed it from simpson.h file, but still am getting an error:
1
2
3
4
5
from pratimas_13.cpp:5:
./simpson.h:5:1: error: expected unqualified-id
{
^
1 error generated.


What this might be? I guess I need to create a project for this program with various header files serving as a functions to be called in source .cpp file (pratimas_13.cpp).
I am using two guards to define different functions (double function and double simpson) in their respective header files, but the error shown above still remains :/
1
2
double simpson(double a, double b, int n, Func) ;
{

I did mention semicolon already once ...


using two guards

What are the "guards" that you mention?
Thanks.

I have removed the semicolon as you instructed - thank you very much. Haven't noticed it before :). However now I am getting errors from if statements (expected this, but am still figuring out how to write them). I am trying to make the if statement check whether the given function is that of fk_1 or that of fk_2. I'm looking at this problem now, but if you have an idea where I might be writing the code incorrectly - I would be very grateful if you could let me know.

Errors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
In file included from pratimas_13.cpp:5:
./simpson.h:12:14: error: cannot initialize a variable of type 'Func'
      (aka 'double (*)(double)') with an rvalue of type 'bool'
    if (Func fk_1 = true)
             ^      ~~~~
./simpson.h:20:24: error: invalid '==' at end of declaration; did you mean '='?
    else if (Func fk_2 == true)
                       ^~
                       =
./simpson.h:20:19: error: cannot initialize a variable of type 'Func'
      (aka 'double (*)(double)') with an rvalue of type 'bool'
    else if (Func fk_2 == true)
                  ^       ~~~~
3 errors generated.


As for the guards I mean this: #include guard, sometimes called a macro guard or header guard to not initialize the same function more than once when including the header into other files more than once. Hope that's clearer.
Last edited on
I am trying to make the if statement check whether the given function is that of fk_1 or that of fk_2.

Why?

1. You seem to do the exact operation regardless of what function it is.

2. The simpson() is not supposed to know or care about the function that it is given. It simply calls the function.
1. I need in my menu to choose which function (x or x^2) to integrate and in simpson() I would like depending on what function is chosen at pratimas_13.cpp the integral to be calculated for that function. I'm thinking of whether I should use do/while loop better. What do you think?

2. Why the simpson() does not care for the function that is given? In its code it has two functions (fk_1 & fk_2), so when I call simpson() I need to make it clear which function calculation to do. Is it for function fk_1 or for function fk_2.

P.S. The problem requires me to send one paramater as a function in the simpson() function, which basically is fk_1 or fk_2 as I've written in pratimas_13.cpp code.
Last edited on
I've rewritten simpson.h file as shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef SIMPSON_H
#define SIMPSON_H
#include <iostream>
#include <cmath>
#include "functionheader.h"

double simpson(double a, double b, int n, Func)
{
  double sum = 0.0;
  double h = (b - a) / n; // base length
  double h2 = h / 2; // half base length
  double x;
    do
    {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h;
    sum += fk_1(left) + 4 * fk_1(left + h2) + fk_1(left + h);
    }
    } while (&fk_1);
    do
    {
    for (int i = 0; i < n; i++)
    {
    double left = a + i * h;
    sum += fk_2(left) + 4 * fk_2(left + h2) + fk_2(left + h);
    }
    } while(&fk_2);

  return h / 6 * sum;   // integral calculation
}
#endif 

However, when I run my program - pratimas_13.cpp - it works until I have to press numbers. When I press 3 everything is ok, but when I press 1 it becomes stuck. The same happens when I press 2. No integral is calculated. I assume the problem might lie in the wrongly written pratimas_13.cpp code. It's given below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <iostream>
#include <cmath>
#include <cstdlib>
#include "functionheader.h"
#include "simpson.h"

void text();

int main()
{
double a, b, f;
int n, m;

printf("a = "); // choose the interval start
scanf("%lf", &a);
printf("b = "); // choose the interval end
scanf("%lf", &b);
printf("n = "); // choose how many steps
scanf("%d", &n);
printf("\n");

  text(); // show the menu
  scanf("%d", &m); // choose which function from text() to integrate
  switch (m)
  {
    case 1:
      f = simpson(a,b,n,fk_1); // should calculate the integral of the first function
      printf("Integral = %3.3f \n", f); // should give the integral of the first function
      break;

    case 2:
      f = simpson(a,b,n,fk_2); // should calculate the integral of the second function
      printf("Integral = %3.3f \n", f); // should give the integral of the second function
      break;

    case 3:
    printf("Quiting...\n"); // quits the program
    return 0;
    break;

    default:
    printf("Incorrect choices.\n"); // if pressed anything ecept 1,2 or 3 gives a menu text again
    text();
    break;
  }
}

void text()
{
  printf("Meniu\r\n\n");
  printf("Which function to integrate?\n");
  printf("f(x) = x - press 1\n");
  printf("f(x) = x^2 - press 2\n");
  printf("Leave menu - press 3\n");
  printf(": ");
}
Last edited on
I've checked the program and understood that the problem with my code is that do/while loop doesn't work. When I remove it - the program works, but it calculates the integral for only the first function in simpson.h header, which is fk_1 and always returns the same value for a=0, b=1 and n=3. Thus, I ask again how can I make pratimas_13.cpp program to choose which function to integrate in simpson.h header (I thought if statement or do/while loop might work) as there I have two sum values ( sum += fk_1(left) + 4 * fk_1(left + h2) + fk_1(left + h); & sum += fk_2(left) + 4 * fk_2(left + h2) + fk_2(left + h);) and need to make the program (pratimas_13.cpp) implement which simpson() to calculate. Is it simpson(a,b,n,fk_1) or is it simpson(a,b,n,fk_2). Do you understand what problem I am dealing with now?
Thus, I ask again how can I make pratimas_13.cpp program to choose which function to integrate in simpson

You already do choose, on the main program.
When you want to integrate the fk_1, you do call f = simpson(a,b,n,fk_1);
When you want to integrate the fk_2, you do call f = simpson(a,b,n,fk_2);

The simpson is given a function. The simpson must compute the integral for that function. Not fk_1 nor fk_2, but for any and every function that the simpson is ever called with.


In my earlier example:
1
2
3
4
double foo( double h, double k, Func fun )
{
  return fun( h * k );
}

The foo() receives some function as argument.
foo() uses name "fun" to refer to that function.
foo() calls the function fun.


Would you please complete this function for us:
1
2
3
4
double simpson2( double start, double end, int steps )
{
  // compute and return the integral of function fk_2
}
Still don't get it why the simpson(a,b,n,fk_2) doesnt give the right result?
Again shouldn't I include if statement in the simpson function to allow the simpson to choose whether to compute the integral for fk_1 or fk_2?

I already made the simpson function to have one of it parameters as the function which to choose to integrate, but it doesnt work? I would like to avoid writing the second simpson in order to have two simpson functions that compute the integrals for fk_1 and fk_2 seperately. The problem asks me to write one simpson function that can calculate the integral of either fk_1 or fk_2. I hope that makes it clearer.

I understand your given example - it's easy. It should go like this:
1
2
3
4
5
6
7
8
9
10
11
12
double simpson2(double start, double end, int steps)
{
  double sum = 0.0; 
  double h = (start - end) / steps; 
  double h2 = h / 2;
  for (int i = 0; i < n; i++)
  {
    double left = a + i * h;
    sum += function(left) + 4 * function(left + h2) + function(left + h);
  }
  return h / 6 * sum;
}
Last edited on
Pages: 12