my program in C has some functionality (#obviously). The program gets input from the user, this user can then choose different implementations, e.g. myProgram -V1, or myProgram -V2 ...
This specification of -V1, -V2, ... decides how the function performs a particular calculation.
E.g..
for (int i = 0; i < len; i ) {
i = myFunctionWhichChangesBehaviorOnUserInput(arr[i]);
}
Now I don't want to create a separate function for each V and then change the respective myFunctionWhichChangesBehaviorOnUserInput() function there.
I know you can do it this way in java.
interface Compute {
double compute(double n);
}
... some imple of Compute
class Task {
Compute compute;
void setCompute(Compute c) {this.compute = c}
double doMyStuff(double[] arr) {
double n = 0;
for (int i = 0; i < arr.length; i ) {
n = compute.compute(arr[i]);
}
return n;
}
}
How can you implement this in C, must be possible somehow.
CodePudding user response:
It can be done by:
- Parse the command line arguments.
- See if the argument matches the list of allowed arguments.
- Call a function in an array of functions based on index from the list of arguments.
We can create a struct containing a valid command line string as well as a pointer to the corresponding function:
typedef void vfunc_t (void);
typedef struct
{
char* str;
vfunc_t* vfunc;
} arg_t;
Then declare an array of such structs:
const arg_t valid_args [3] =
{
[0] = {.str="-V1", .vfunc=v1func },
[1] = {.str="-V2", .vfunc=v2func },
[2] = {.str="-V3", .vfunc=v3func },
};
Full example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef void vfunc_t (void);
typedef struct
{
char* str;
vfunc_t* vfunc;
} arg_t;
// some functions with different behavior:
void v1func (void) { puts(__func__); }
void v2func (void) { puts(__func__); }
void v3func (void) { puts(__func__); }
// callback function to bsearch for our arg_t type:
static int argcmp (const void* o1, const void* o2)
{
const arg_t* a1 = (const arg_t*)o1;
const arg_t* a2 = (const arg_t*)o2;
return strcmp(a1->str, a2->str);
}
int main (int argc, char* argv[])
{
const arg_t valid_args [3] =
{
[0] = {.str="-V1", .vfunc=v1func },
[1] = {.str="-V2", .vfunc=v2func },
[2] = {.str="-V3", .vfunc=v3func },
};
if(argc != 2)
{
puts("Usage: yadayada...");
return 0;
}
/*
As the strings are sorted in alphabetic order, bsearch
is the most efficient way to find the matching one.
Overkill in this simple example, but not when there's
hundreds of options.
*/
arg_t key = {argv[1], NULL };
arg_t* arg = bsearch(&key,
valid_args,
sizeof valid_args/sizeof *valid_args,
sizeof *valid_args,
argcmp);
if(arg == NULL)
{
puts("Usage: yadayada...");
return 0;
}
size_t index = arg - valid_args; // pointer arithmetic on the struct array
vfunc_t* vfunc = valid_args[index].vfunc; // table look-up
vfunc(); // call the function matching the command-line argument
}
Note: This code is sparse with error handling. Consider adding bounds checks, argv sanitizing and similar.
CodePudding user response:
It sounds like you want function pointers.
#include <stddef.h>
#include <stdio.h>
typedef void (*compute_t)(double);
void printing_a(double);
void printing_b(double);
double arr[5] = {1.0, 2.0, 3.0, 3.5, 4.0};
size_t len = 5;
int main(int argc, char *argv[]) {
compute_t myfunction;
if (argc > 2) {
myfunction = printing_a;
} else {
myfunction = printing_b;
}
for (size_t i = 0; i < len; i ) {
myfunction(arr[i]);
}
}
void printing_a(double n) {
printf("printing_a(%f)", n);
}
void printing_b(double n) {
printf("printing_b(%f/2)", n*2.0);
}
You can set the function pointer, and then call the function pointed to by the pointer. This is analogous to your Java code.