This is my first time working with pointers to function.
What I'm trying to do is create a function called essay, that gets a pointer to another function , an integer num, and then num doubles.
The function essay, will multiply the arguments, and then return the value of the function i recieved as an argument, with the product.
This sounds complex but it really is quite simple.
Example:
essay(sin,2,pi,1/2) will return the value of sin(pi/2)
this is my code...for some reason it doesnt let me send the pointer to the function sin. Says no instance of overloaded function sin matches argument list, but this is exactly how i saw my teacher do it...I think.
#include <stdio.h>
#include <conio.h>
#include <stdarg.h>
#include <math.h>
double (*pfunc)(double);
double essay(double* pfunc(double),double num, ... )
{
int i;
double product=1,result;
va_list arguments;
va_start(arguments,num);
for(i=0;i<num;i++)
product*=va_arg(arguments,double);
va_end(arguments);
result=*(pfunc(product));
return result;
}
void main()
{
double x,y;
x=3.14159265358979323846;
y=0.5;
printf("%lf",essay(sin,2,x,y));
getch();
}
this is wrong
double essay(double* pfunc(double),double num, ... )
Here you're passing a function as a parameter which return a pointer to double, that not make sense, should be:
double essay(double (*pfunc)(double),double num, ... )
Here you're passing a pointer to a function which returns a double and receive a double as a parameter
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
// removed extra var
double essay(double (*pfunc)(double), double num, ...) // added parens
{
int i;
double product = 1, result;
va_list arguments;
va_start(arguments, num);
for (i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
result = pfunc(product); // removed extra parens
return result;
}
void main()
{
double x, y;
x = 3.14159265358979323846;
y = 0.5;
printf("%lf", essay(sin, 2, x, y));
}
This is what I'd do, assuming a C99 compiler that accepts variable declarations in for loops and at arbitrary points in a block of code. Note the use of the typedef for the function pointer type (MathFunc2 would be for a function that takes two arguments, etc), and the use of int (rather than double) for the number of values in the argument list.
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
typedef double (*MathFunc1)(double);
static double essay(MathFunc1 function, int num, ...)
{
double product = 1.0;
va_list arguments;
va_start(arguments, num);
for (int i = 0; i < num; i++)
product *= va_arg(arguments, double);
va_end(arguments);
double result = (*function)(product);
return result;
}
int main(void)
{
double x = 3.14159265358979323846; // M_PI?
double y = 0.5;
printf("%f\n", essay(sin, 2, x, y));
}
Related
I am learning how to use functions passing through pointers.
I have a function that chops a double d into two parts, the whole_part and the fraction_part. So “425.25” would be chopped into “425” and “.25”.
I'm getting errors related to passing through pointer types. I'm not sure where problems like this arise. Any help would be appreciated!
#include <math.h>
#include <stdio.h>
#include <limits.h>
void chop(double, long *, double *);
int main(void)
{
double d;
long * whole_part;
double * fraction_part;
printf("enter a double ");
scanf("%lf", &d);
// Call the function
chop(d, &whole_part, &fraction_part);
printf("%.10lf chopped is %ln and %.10lf", d, whole_part, fraction_part);
return 0;
}
void chop(double d, long *whole_part, double *fraction_part)
{
*whole_part = (int)d;
*fraction_part = d - (double)whole_part;
}
Initial problems:
long whole_part and double fraction_part should not be initialized in main as their variable pointers.
The function chop() should call the pointer to whole_part when attempting to use it to determine fraction_part.
#include <stdio.h>
#include <limits.h>
void chop(double, long *, double *);
int main(void)
{
double d;
long whole_part;
double fraction_part;
printf("enter a double ");
scanf("%lf", &d);
// Call the function
chop(d, &whole_part, &fraction_part);
printf("%.10lg chopped is %li and %.10lg\n", d, whole_part, fraction_part);
return 0;
}
void chop(double d, long *whole_part, double *fraction_part)
{
*whole_part = (int)d;
*fraction_part = d - (double)*whole_part;
}
#include "stdio.h"
int add(int x, int y)
{
return x + y;
}
int withFive(int x, int (*func))
{
return (*func)(x,5);
}
int main()
{
void (*funcptr)(int) = &add;
printf("%d", withFive(10,funcptr));
return 0;
}
This code seems like it would compile based on my understanding of function pointers but there is an error that a function or function pointer isn't being passed to withFive. How should I write withFive so that the compiler will accept the argument as a function ptr?
The definition should be
int withFive(int x, int (*func)(int, int ) )
or
int withFive(int x, int (*func)(int x, int y) )
like in a variable definition.
Btw: void (*funcptr)(int) = &add; should be int (*funcptr)(int,int) = &add; as well or just int (*funcptr)(int,int) = add;
int withFive(int x, int (*func))
You want, as an argument, a function func that returns int and takes two int as parameter.
So you need:
int withFive(int x, int (*func)(int, int))
Then:
{
return (*func)(x,5);
}
You don't need to dereference func. Just write
return func(x, 5);
Then:
void (*funcptr)(int) = &add;
That's the wrong type again. And you don't need to take the address of add. Just write:
int (*funcptr)(int, int) = add;
Or you could just write:
printf("%d", withFive(10,add));
Generally speaking, to make handling the somewhat awkward function pointer syntax easier and the result more readable, you could use a typedef. All together, and some other minor edits included:
#include <stdio.h>
typedef int (*binary_func_t)( int, int );
int add( int x, int y )
{
return x + y;
}
int withFive( int x, binary_func_t func )
{
return func( x, 5 );
}
int main()
{
printf( "%d\n", withFive( 10, add ) );
return 0;
}
In your case it would have to be int withFive(int x, int (*func)(int,int)). However, using the raw function pointer syntax of C is quite unreadable. The recommended practice is to always use typedefs, like this:
typedef int operation_t (int x, int y); // function type acting as "template"
int add (int x, int y);
int withFive(int x, operation_t* op); // op is a pointer to function
...
withFive(10, add);
The title says it all. Can function be passed as argument in variadic function and if so, how can I access it?
#include <stdio.h>
#include <stdarg.h>
#include <math.h>
void func(double x, int n, ...){
va_list fs;
va_start(fs, n);
for (int i = 0; i < n; i++)
{
va_arg(fs, *); //this is where I get confused
}
}
int main(){
double x = 60.0 * M_PI / 180.0;
func(x, 3, &cos, &sin, &exp);
}
The second argument to va_args is the type to convert to. In this case each function has compatible types, specifically they take a single double as an argument and return a double. The type of a pointer to such a function is double (*)(double), so that it what you would use for the type.
double (*f)(double) = va_arg(fs, double (*)(double));
double result = f(x);
Also, don't forget to call va_end(fs); after the loop.
I have this homework to do: "Determine the minimum of 10 precision double numbers from a string (implicit values or from the KB) using a function with a variable number of parameters. The first 7 values will be considered initially, next the last 3 and at the end these 2 values." Well I made it all but I don't know why it gives me some strange results. Here's the code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <conio.h>
double min(double,...);
void main(){
double a,b,c;
printf("Introduceti numerele: ");
scanf("%lf%lf%lf",&a,&b,&c);
printf("\nMinimul este %lf",min(10,1.34,4.34,7,5.23,6.23,2,8.232,a,b,c));
_getch();
}
double min(double x,...){
int i;
double y;
va_list ap;
va_start(ap,x);
y=va_arg(ap,double);
for(i=0;i<x;i++){
if(y>va_arg(ap,double))
y=va_arg(ap,double);
}
va_end(ap);
return y;
}
Also i don't know why the compiler knows about what argument is next cause i is not used in va_arg(ap,double).
for(i=0;i<x;i++){
if(y>va_arg(ap,double))
y=va_arg(ap,double);
The first parameter in the call to your function min is the number of arguments, and it has the type int:
#include <stdarg.h>
double min( int numberOfArgs, ... )
// ^^^
{
va_list argptr;
va_start( argptr, numberOfArgs ); // initialize argument pointer
double minData = va_arg( argptr, double ); // initialize the minimum with the first argument
// and increment argument pointer
for ( int i = 1; i < numberOfArgs; i ++ ) // for all of the following arguments
{
double data = va_arg( argptr, double ); // get argument and increment argument pointer
if ( data < minData ) // test if argument is less than mnimum
minData = data;
}
va_end( argptr );
return minData;
}
Ensure that all of your arguments in the argument list are floating point values of type double:
int main()
{
double a, b, c;
printf("Introduceti numerele: ");
scanf_s("%lf%lf%lf", &a, &b, &c);
double minVal = min( 10, 1.34, 4.34, 7.0, 5.23, 6.23, 2.0, 8.232, a, b, c)
// ^^ ^^
printf("\nMinimul este %lf", minVal);
return 0;
}
Can we pass variable number of arguments to a function in c?
Here is an example:
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
int maxof(int, ...) ;
void f(void);
int main(void){
f();
exit(EXIT SUCCESS);
}
int maxof(int n_args, ...){
register int i;
int max, a;
va_list ap;
va_start(ap, n_args);
max = va_arg(ap, int);
for(i = 2; i <= n_args; i++) {
if((a = va_arg(ap, int)) > max)
max = a;
}
va_end(ap);
return max;
}
void f(void) {
int i = 5;
int j[256];
j[42] = 24;
printf("%d\n", maxof(3, i, j[42], 0));
}
If it is a function that accepts a variable number of arguments, yes.
Yes, if the function accepts variable arguments. If you need to make your own variable-argument function, there are macros that begin with va_ which give you access to the arguments.
make sure that the variable argument list should always be at the end of the argument list
example: void func(float a, int b, ...) is correct
but void func(float a, ..., int b) is not valid
"You should consider that using variadic functions (C-style) is a dangerous flaw," says Stephane Rolland. You can find his helpful post here.