Pregunta

En C, ¿hay alguna manera de llamar a una función con argumentos almacenados en alguna matriz?Soy un novato en C, ni siquiera estoy seguro de si esto es correcto, pero por ejemplo:

void f0(int a) { ... };
void f1(int a, int b) { ... };
void f2(int a, int b, int c) { ... };

int array[5][2][?] = [
    [&f0, [5]],
    [&f1, [-23, 5]],
    [&f2, [0, 1, 2]],
    [&f2, [1235, 111, 4234]],
    [&f0, [22]]
];

int i;
for (i = 0; i < 5; i++) {
    APPLY?(array[i][0], array[i][1])
}

PD:¿Qué tipo de estructura debo usar cuando los elementos de la matriz varían en longitud?

En Python, esto sería:

def f0(a): ...
def f1(a, b): ...
def f2(a, b, c): ...

array = [
    (f0, (5,)),
    (f1, (-23, 5)),
    (f2, (0, 1, 2)),
    (f2, (1235, 111, 4234)),
    (f0, (22,))
]

for f, args in array:
    apply(f, args)
¿Fue útil?

Solución

Es posible tener funciones Arity variables en C, pero el mecanismo es torpe y tiene ciertas restricciones, es decir, debe haber al menos un parámetro fijo, y tiene que ser capaz de decir a partir de los parámetros fijos o de la variable propios parámetros, donde al final de la lista de variables es.

Una solución más típica, uno que juega a las fortalezas de C en lugar de sus debilidades, es algo así como este ejemplo. ( Actualizado con los punteros de función .)

#include <stdio.h>

void f1(int, int *);
void f2(int, int *);

struct BoxOfInts {
    void (*f)(int,int *);
    int howMany;
    int theNumbers[4];
} intMachine[] = {
    {f1, 1,  { 5,  }},
    {f2, 2,  { -23, 5  }},
    {f1, 3,  { 0, 1, 2  }},
    {f2, 3,  { 1235, 111, 4234  }},
    {f1, 1,  { 22,  }},
    { 0 }
};

void dispatch(void)
{
    for(struct BoxOfInts *p = intMachine; p->f; ++p)
        (*p->f)(p->howMany, p->theNumbers);
}

void f1(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f1 %d %d\n", howMany, t);
    }
}

void f2(int howMany, int *p)
{
    while (howMany-- > 0) {
        int t = *p++;
        printf("f2 %d %d\n", howMany, t);
    }
}

int main()
{
  dispatch();
  return 0;
}

Otros consejos

En realidad no, no.

Una mejor manera de hacer esto en C sería definir sus funciones a todos tienen la misma firma, como:

void f0(int size, int elements[])

y luego pasar matrices del tamaño adecuado a sus funciones.

// this is a function pointer
void (*x)(int, int[]); 
...
// set x to point at f0
x = f0;
// call x (ie: f0) with 1 element from position 5 of array
x(1, &(array[5]));

Creo que tal vez lo que desea es:

array[i][0](array[i][1]);

Para llamar a una función de su puntero en C sólo requiere que el operador de llamada de función, que es paréntesis.

enlace posiblemente útil: http://boredzo.org/pointers/

c no tiene una noción incorporada de listas o comprensión de la lista, debe configurar un bucle explícito sobre una matriz y debe admitir la longitud de la lista usted mismo.

Sí, esto tiene más palabras que la forma de Python, pero eso se debe a que Python maneja los detalles por usted.

Estructuras de datos que son razonablemente adecuadas para manejar "listas" nocionales:

  • matrices dinámicas (posiblemente envueltas en un struct para permitirle mantener metainformación como la longitud actual y la longitud asignada en el mismo lugar)
  • listas enlazadas

Si elige una solución basada en matrices, necesitará:

  1. realizar un seguimiento de la longitud actual y pasarla a las funciones de procesamiento
  2. use un centinela para marcar el final de los datos (lo que podría significar usar un tipo de datos más grande para permitirle especificar un centinela que no puede aparecer en los datos)

Las listas enlazadas se pueden procesar nodo por nodo porque tienen un final natural.

#include <stdio.h> 

void f0(int a              ){ printf("f0(%i)\n",      a    ); }
void f1(int a, int b       ){ printf("f1(%i,%i)\n",   a,b  ); }
void f2(int a, int b, int c){ printf("f2(%i,%i,%i)\n",a,b,c); }

typedef void (*f_arg1)(int);
typedef void (*f_arg2)(int,int);
typedef void (*f_arg3)(int,int,int);

struct fn_call {
  f_arg1 fn;
  int arg_num;
  int *args;
} array[] = {  { (f_arg1)f0, 1, (int[]){5}               },
               { (f_arg1)f1, 2, (int[]){-23, 5}          },
               { (f_arg1)f2, 3, (int[]){0, 1, 2}         },
               { (f_arg1)f2, 3, (int[]){1235, 111, 4234} },
               { (f_arg1)f0, 1, (int[]){22}              }   };

void apply( struct fn_call *call ){
  switch( call->arg_num ){
  case 1: ((f_arg1)call->fn)( call->args[0] );                  break;
  case 2: ((f_arg2)call->fn)( call->args[0], call->args[1] );   break;
  case 3: ((f_arg3)call->fn)( call->args[0], call->args[1], call->args[2] );
  }
}

int main(){
  for(unsigned i=0; i<sizeof(array); i++)  apply( &array[i] );
}

Resultados:

f0(5)
f1(-23,5)
f2(0,1,2)
f2(1235,111,4234)
f0(22)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top