Home > OS >  C change behavior of function on behalf of input
C change behavior of function on behalf of input

Time:07-08

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.

  • Related