1

I'm struggling with pointers in C. I have to write a program that will make a 3 operations on one number (sqrt, sin, exp) using functions and pointers. I have done it but I have a problem to write a function that takes as parameter a pointer to any of the above functions + a floating point number, returning the result of the corresponding calculation. In main function I attached working code without this function. I don't have any idea how to write this function and I wrote my try in this code. Here I attach code which I have wrote:

#include <stdio.h>
#include <math.h>

double square(double *);
double sinus(double *);
double exponential(double *);
void count(*square, double result);

double number, square_result, sinus_result, exponential_result;

int main()
{

    printf("Give number: ");
    scanf("%lf", &number);

    square_result = square(&number);
    sinus_result = sinus(&number);
    exponential_result = exponential(&number);

    printf("%lf\n", square_result);
    printf("%lf\n", sinus_result);
    printf("%lf", exponential_result); 

}

double square(double *x)
{
    double square_result;
    square_result = sqrt(*x);

    return square_result;
}

double sinus(double *x)
{
    double sinus_result;
    sinus_result = sin(*x);

    return sinus_result;
}

double exponential(double *x)
{
    double exponential_result;
    exponential_result = exp(*x);

    return exponential_result;
}

void count(*square, double result)
{
    result = square(&number);
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335

3 Answers3

1

I created a function call_functaking a pointer on a function as an argument and a double* like the following:

//arguments are a pointer to any functions taking argument double* and a double* number
double call_func(double (*MyFunction)(double* arg), double* number)
{
    return (MyFunction)(number);
}

// a small edit, imho you do not need to pass number by pointer

This shall be called like this:

    square_result = call_func(square, number);
    sinus_result = call_func(sinus, number);
    exponential_result = call_func(exponential,number);

Here it is, integrated in your code:


// here is my function that takes a function pointer as an argument
double call_func(double (*MyFunction)(double* arg), double number);


int main()
{

    printf("Give number: ");
    scanf("%lf", &number);

    square_result = square(&number);
    sinus_result = sinus(&number);
    exponential_result = exponential(&number);

    printf("%lf\n", square_result);
    printf("%lf\n", sinus_result);
    printf("%lf", exponential_result);
    // call of my general function

    printf("\n********************************\n");
    printf("\n\nUSAGE OF FUNCTION POINTER \n");

    double square_result2 = 0.0;
    double sinus_result2 = 0.0;
    double exponential_result2 =0.0;

    square_result2 = call_func(square, &number);
    sinus_result2 = call_func(sinus, &number);
    exponential_result2 = call_func(exponential, &number);

    printf("%lf\n", square_result2);
    printf("%lf\n", sinus_result2);
    printf("%lf", exponential_result2);

}


//arguments are a pointer to any functions taking argument double and a double number
double call_func(double (*MyFunction)(double* arg), double* number)
{
    return (MyFunction)(number);
}

Pat. ANDRIA
  • 2,330
  • 1
  • 13
  • 27
  • Thanks. A very small suggestion: may be better to use `double` and not `double*` in your functions. It will improve readability and avoids calling with `&`. `Passing by pointers when you must and by value when you can.` Here you do not modify the argument in the functions so you can pass by value. – Pat. ANDRIA Feb 12 '21 at 18:35
0

For starters there is no any sense to declare the function parameter as having the pointer type double *.

double square(double *);
double sinus(double *);
double exponential(double *);

because the passed by reference object of the type double is not being changed within the functions.

Declare the functions like

double square(double );
double sinus(double );
double exponential(double );

and they will be called like

square_result = square( number);
sinus_result = sinus( number);
exponential_result = exponential(number);

All these functions have the type

double( double)

or the type of a pointer to such a function will look like

double ( * )( double )

So you can declare the required function for example like

double f( double calc( double ), double value );

or equivalently

double f( double ( * calc )( double ), double value );

where instead of f and calc you can use your own names.

And the function can be called for example like

double result = f(  square, number );

And within the function you can write

double f( double ( * calc )( double ), double value )
{
    return calc( value );
}

You could declare an array of pointers to the functions like

double ( *fp[] )( double ) = { square, sinus, exponential };
size_t N = sizeof( fp ) / sizeof( *fp );

And call the functions in a loop

for ( size_t i = 0; i < N; i++ _
{
    double result = f(  fp[i], number );
    //...
}

To make this declaration

double ( *fp[] )( double ) = { square, sinus, exponential };

simpler you can introduce a typedef name. For example

typedef double Func( double );

in this case the array declaration will look like

Func * fp[] = { square, sinus, exponential };
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Or preferably `typedef double myfunc_t (double);` then `double f (myfunc_t* calc, double value)`. – Lundin Feb 12 '21 at 12:53
0

Referring to your code, use EITHER (1) pointer OR (2) return values.

(1) means the original variable (original address) is used and can be changed in subroutine. Then nothing needs to be returned.

(2) a value of variable is provided to subroutine, and the subroutine will return the result. Then the input parameter to the subroutine doesn't need to be a pointer.

Then (1) is (be aware that the input value is replaced by result value)

void square_root(double *x)
{
    *x = sqrt(*x);
}

or (1) if you do not want input to be replaced by result

void square_root(double a, double *x)
{
    *x = sqrt(a);
}

or (2) is

double square_root(double a)
{ 
   double r;       
   r = sqrt(a);
   return r;
}

or (2) in a shorter way is

double square_root(double a)
{ 
   return sqrt(a);
}

COMMENT: Usually, here I would just go for the first (2) version. Otherwise, if you would like to use pointer, e.g. because you would like to get several values from the subroutine anyway, then go for the second version of (1).

COMMENT 2: Pointers can be very useful. Sometimes pointers are (almost) the only solution. You need to be familiar with using pointers. If not, you rather introduce a potential risk, if something is not quite right. You need to learn why that is the case.

COMMENT 3: About pointer to functions. I recommend, first understand the concept of pointers to data. And skip pointer to functions for now, unless you need it for school. Then the following might be a good reference: How do function pointers in C work?

sidcoder
  • 460
  • 2
  • 6