Function pointers as function arguments

Hello, I am a beginner at c++. I am trying to figure out how to write this program. I have been stuck for days, any help would be greatly appreciated.
Here is the question:
Write a program which will display a menu with the options Square, Cube, Fourth Power and Quit. Accept S, C, F or Q from the user, non-case sensitive. Do not forget to validate the user input. When a valid option is selected, the program will begin tabulating the selected function in an interval. Ask the user for two integers in the range 0 to 100, to be used as interval boundaries. Tabulate the selected function (Square, Cube, or Fourth Power) for all integers within the interval. To implement the tabulation, use a C++ function with a function pointer argument (so that you can pass to it function square, cube, or fourthPower as an actual argument). Specify function preconditions in comments before functions and use assertions to check the function preconditions (e.g., that the interval boundaries passed to the tabulating function are between 0 and 100). Provide well formatted, easily readable output.



my code so far:


#include <iostream>
using namespace std;

int main ()
{
char input;
int interval;

{
cout << " ::Menu::\n\n"
<< "1. Square (S)\n\n"
<< "2. Cube(C)\n\n"
<< "3. Fourth Power(F)\n\n"
<< "4. Quit Program(Q)\n\n"
<< "Choice: ";
cin >> input;

switch(input)
{
case 'S':
case 's':
cout << "Choose two integers between 0-100 for interval boundries " <<endl;
cin >> interval;
cin >> interval;
break;

case 'C':
case 'c':
cout << "Cube: " <<endl;
break;

case 'F':
case 'f':
cout << "Fourth Power: "<<endl;
break;

default:
cout << "Invalid selection. Please try again." <<endl;
}

} while(!((input == 'Q') ||(input == 'q')));
system("PAUSE");

}






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>

// type alias for a unary function with parameter of type int and returning a prvalue of type int
using function_type = int(int) ; // 1. C++11 syntax for type alias
typedef int function_type(int) ; // 2. classic typedef; same as above

// type alias for pointer to function of type function_type
using ptr_function_t = function_type* ; // 3. C++11 syntax for type alias
typedef function_type* ptr_function_t ; // 4. classic typedef; same as above
typedef function_type *ptr_function_t ; // 5. classic typedef; same as above
using ptr_function_t = int(*)(int) ; // 6. same as above, ugly syntax
typedef int (*ptr_function_t)(int) ; // 7. same as above, uglier syntax

// note: programmers who like to emphasise semantics over syntx favour 1/2, 3/4, 6
//       programmers who like to emphasise syntax over semantics favour 2, 5/7
//       pick the one that appeals to you, and be consistent (use the same style everywhere)

// a C++ function "with a function pointer argument" (with a parameter of type ptr_function_t)
// invariant: ptr_function is not null
// invariant: evaluation of ptr_function(arg) does not cause a signed integer overflow
int call_function( ptr_function_t ptr_function, int arg )
{
    // a pointer to a function is a 'callable object'.
    return ptr_function(arg) ;  // call the function which is pointed to by ptr_function

    // or, same as above:
    // dereference pointer to function to get an lvalue of type function and call the function
    // return (*ptr_function)(arg) ; // avoid; does not work with other kinds of callable objects
}

// a function of type function_type
int reverse( int arg ) // invariant: arg in [0,100]
{
    if( arg == 100 ) return 1 ;
    else if( arg < 10 ) return arg ;
    else return (arg%10) * 10 + (arg/10) ;
}

int main()
{
    int v = 72 ;

    // pass pointer to function 'reverse' as the first argument, v as the second argument
    int rv = call_function( &reverse, v ) ;

    // implicit converstion from lvalue of type function_type to prvalue of type pointer to function_type
     rv = call_function( reverse, v ) ;

    std::cout << rv << ' ' << reverse(v) << ' ' << call_function( reverse, v ) << '\n' ;

    // exercise in calling functions:
    std::cout << v << ' ' << reverse(rv) << ' ' << reverse( reverse(v) ) << ' '
              << call_function( reverse, rv ) << ' ' << call_function( &reverse, rv )
              << ' ' << call_function( &reverse, call_function( reverse, v ) ) << '\n' ;
}

http://coliru.stacked-crooked.com/a/9be0ef1738f5be1c
Im sorry but im still confused, can you explain it. I am a beginner.
Let's take it one step at a time.

For convenience, we can create an alias for any type. A type alias is simply another name for a type.

We can create a type alias with a typedef
1
2
3
typedef unsigned int uint ; // uint is an alias for the type unsigned int
unsigned int a = 0 ;
uint b = 0 ; // type of 'b' is 'unsigned int'  


We can also create a type alias with an alias declaration (using)
1
2
3
using uint = unsigned int ; // uint is an alias for the type unsigned int
unsigned int a = 0 ;
uint b = 0 ; // type of 'b' is 'unsigned int'  


A function has a type.
The type of the function int foo( int arg ) is int(int)
The type of the function void bar( int a1, double a2 ) is void(int,double)

This creates an alias for a type - in this case, the type is the type of a function: using function_type = double(int) ;
With this, function_type and double(int) are synonyms;
the type is 'function accepting a single parameter of type int and yielding a result of type double'
double baz( int a ) { return a * 0.5 ; } is a function of this type.

Have you understood this much?
a little bit, but I still don't know where to start on how to begin writing this program im really stuck on it.
If T is a type, the type T* is 'pointer to T'
For instance:
The type int* is 'pointer to int'
The type const int* is 'pointer to const int'


So, if we have using function_type = int(int) ;
The type function_type* is 'pointer to function of type int(int)'.

And int my_function( function_type* pfn, int v ) ; is a function taking two arguments.
The type of the first argument 'pfn' is 'pointer to function of type int(int)'

Within my_function, we can call the function that is pointed to by 'pfn' this way:
1
2
3
4
5
6
7
using function_type = int(int) ;

int my_function( function_type* pfn, int v )
{
    int result = pfn(v) ; // pfn != nullptr
    return result ;
}


Have you understood this much?

my code so far

[#include <iostream>
using namespace std;

double square(double);
double cube(double);
double fourthPower(double);
void tabulateFunction(int, int, double ptFunc(double));


int main()
{
char choice;
int lowerBound = 0-100;
int upperBound = 0-100;
double (*ptFunc)(double);


cout << "\t\tMenu" << endl;
cout << "\tS: Square" << endl;
cout << "\tC: Cube" << endl;
cout << "\tF: Fourth Power" << endl;
cout << "\tQ: Quit" << endl;
cout << "Please choose s,c,f or q. Then choose 2 integers between 0-100: " <<endl;

cin >> choice;

//Make choice capitalized if lowercase
if(choice >= 'a' && choice <= 'z')
choice = (choice - 'a') + 'A';

cin >> lowerBound;
cin >> upperBound;


switch(choice)
{
case 'S': ptFunc = &square; break;
case 'C': ptFunc = &cube; break;
case 'F': ptFunc = &fourthPower; break;
case 'Q': cout << "Quitting" << endl; break;
default:
cout << "Invalid Selection. Please try Again." << endl;
}

tabulateFunction(lowerBound,upperBound,*ptFunc);
return 0;
}

void tabulateFunction(int lower, int upper, double ptFunc(double))
{
cout << "The range of numbers selected is from " << lower << " to " << upper << endl;
for(double i=lower;i<upper;i++)
{
cout << i << ": " << ptFunc(i) << endl;
}
}

double square(double num)
{
double squared = num*num;
return squared;
}
double cube(double num)
{
double cubed = num*num*num;
return cubed;
}
double fourthPower(double num)
{
double fourthpower = num*num*num*num;
return fourthpower;


}
[/code]
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
// using namespace std ;
#include <cctype> // for std::topper
#include <cassert> // for assert

int square( int v ); // precondition: v is in the range [0,100]
int cube( int ); // precondition: v is in the range [0,100]
int fourthPower( int ); // precondition: v is in the range [0,100]

void tabulateFunction( int, int, int ptFunc( int ) );

// precondition: lbound and ubound are in the range [0,100]
// precondition: lbound < ubound
void tabulateFunction( int lbound, int ubound, int ptFunc( int ) );

int main()
{
    char choice;
    /*
    int lowerBound = 0 - 100;
    int upperBound = 0 - 100;
    */
    int lowerBound ;
    int upperBound ;
    int ( *ptFunc )( int );


    std::cout << "\t\tMenu" << '\n';
    std::cout << "\tS: Square" << '\n';
    std::cout << "\tC: Cube" << '\n';
    std::cout << "\tF: Fourth Power" << '\n';
    std::cout << "\tQ: Quit" << '\n';
    std::cout << "Please choose s,c,f or q. Then choose 2 integers between 0-100: " << '\n';

    std::cin >> choice ;

    //Make choice capitalized if lowercase
    /*//////////////////////////////////////////
    if( choice >= 'a' && choice <= 'z' )
    choice = ( choice - 'a' ) + 'A';
    //////////////////////////////////////////*/
    choice = std::toupper(choice) ; // http://en.cppreference.com/w/cpp/string/byte/toupper

    // std::cin >> lowerBound;
    // std::cin >> upperBound;

    switch( choice )
    {
        case 'S':
            ptFunc = &square;
            break;
        case 'C':
            ptFunc = &cube;
            break;
        case 'F':
            ptFunc = &fourthPower;
            break;
        case 'Q':
            std::cout << "Quitting" << '\n';
            // break;
            return 0 ;
        default:
            std::cout << "Invalid Selection. quitting." << '\n';
            return 1 ; // EXIT_FAILURE
    }

    std::cin >> lowerBound >> upperBound ;

    if( lowerBound < 0 || upperBound > 100 || lowerBound > upperBound )
    {
        std::cout << "invalid range. quitting.\n" ;
        return 1 ; // EXIT_FAILURE
    }
    else
    {
        tabulateFunction( lowerBound, upperBound, ptFunc );
    }

    // return 0; // implicit
}

void tabulateFunction( int lower, int upper, int ptFunc( int ) )
{
    // assert the preconditions
    assert( lower >= 0 && upper <= 100 && lower < upper ) ;

    std::cout << "The range of numbers selected is from " << lower << " to " << upper << '\n';
    for( int i = lower; i < upper; i++ ) // ***  i <= upper if the range is [lower,upper]
                                         // ie. from lower up to and including upper
    {
        std::cout << i << ": " << ptFunc( i ) << '\n';
    }
}

int square( int num )
{
    /*
    int squared = num * num;
    return squared;
    */

    // assert the precondition
    assert( num >= 0 && num <= 100 ) ;
    return num * num ;
}

int cube( int num )
{
    /*
    int cubed = num * num * num;
    return cubed;
    */

    // assert the precondition
    assert( num >= 0 && num <= 100 ) ;
    return num * num * num;
}

int fourthPower( int num )
{
    /*
    int fourthpower = num * num * num * num;
    return fourthpower;
    */

    // assert the precondition
    assert( num >= 0 && num <= 100 ) ;
    return num * num * num * num;
}
Wow thanks a bunch!!!!
Topic archived. No new replies allowed.