3

Cでは、引数を配列に格納して関数を呼び出す方法はありますか? 私はCの初心者です。これが正しいかどうかさえわかりませんが、例:

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])
}

PS: 配列の項目の長さが異なる場合、どのような構造を使用すればよいですか?

Python では、これは次のようになります。

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)
4

5 に答える 5

2

そうではありません。

Cでこれを行うためのより良い方法は、次のように、すべてが同じシグネチャを持つように関数を定義することです。

void f0(int size, int elements[])

次に、適切なサイズの配列を関数に渡します。

// 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]));
于 2009-10-08T16:16:05.743 に答える
2

C で可変アリティ関数を使用する可能性はありますが、メカニズムは扱いにくく、特定の制限があります。つまり、少なくとも 1 つの固定パラメーターが必要であり、固定パラメーターまたは可変パラメーター自体から、どこにあるかを知ることができる必要があります。変数リストの最後です。

C の短所ではなく長所を活かす、より典型的なソリューションは、次の例のようなものです。(関数ポインタで更新。)

#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;
}
于 2009-10-08T16:22:15.073 に答える
0

おそらくあなたはただ欲しいと思います:

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

C でポインターから関数を呼び出すには、かっこである関数呼び出し演算子のみが必要です。

おそらく役立つリンク: http://boredzo.org/pointers/

于 2009-10-08T16:22:34.967 に答える
0

cには、リストまたはリスト内包表記の組み込みの概念がありません。配列に対して明示的なループを設定する必要があり、リストの長さを自分でサポートする必要があります。

はい、これは Python の方法よりも冗長ですが、それは Python が詳細を処理しているためです。

概念的な「リスト」の処理に適したデータ構造:

  • struct動的配列 (現在の長さと同じ場所に割り当てられた長さなどのメタ情報を保持できるように、 a でラップされる可能性があります)
  • リンクされたリスト

アレイ ベースのソリューションを選択した場合は、次のいずれかを行う必要があります。

  1. 現在の長さを追跡し、それを処理関数に渡します
  2. センチネルを使用してデータの終わりをマークします (これは、より大きなデータ型を使用して、データに表示できないセンチネルを指定できるようにすることを意味する場合があります)

リンクされたリストは、自然な終わりがあるため、ノードごとに処理できます。

于 2009-10-08T16:52:08.883 に答える
0
#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] );
}

結果:

f0(5)
f1(-23,5)
f2(0,1,2)
f2(1235,111,4234)
f0(22)
于 2009-10-08T17:19:59.077 に答える