0

Cの関数から複数の値を返す方法を見つけようとしています.

たとえば、私が持っているとしましょう

int compute(int a, int b)
{
int c;
// do some computation on a,b,c
// return a,b,c
}

今、私はこれらの値を配列で返すことができます。私はそれをやろうとしていましたが、配列は動的である必要があるので、main() でも参照できることに気付きました。

別の方法は、構造体を作成してから構造体変数を返すことです。

上記の回避策以外に、これを行う簡単で堅牢な方法はありますか? メソッドから互いに独立した約25の異なる計算値を返す必要があり、コードにはすでに多くの構造体があります。

ありがとうございました。

4

8 に答える 8

6

たとえば、Python with。のように、複数の変数を簡単に返すことはできませんreturn (a,b,c)。ただし、他の「戻り値」に設定されているポインターを渡すか、構造体を使用することができます。

場違いの

関数が実際に個別の値を返し、その引数を変更しないようにする場合、簡単な方法は追加のポインターを渡すことです(構造体を使用することもできます)。たとえば、この関数は、数値のペアの合計と差を計算します。

int add_sub(int a, int b, int* ret2) {
   if (ret2) *ret2 = a - b;
   return a + b;
}

を使用if (ret1)すると、ポインタ引数として安全に渡すNULLことができるため、その戻り値を無視できます。あなたはこれを次のように使用します:

int add, sub;
add = add_sub(10, 3, &sub);
// add == 13, sub == 7

int just_add;
just_add = add_sub(15, 5, NULL);
// just_add == 20

(この手法では、同じ引数を2回渡すと、混乱を招く可能性があります。たとえばa = add_sub(a, b, &b)、必要なものが得られない場合などです。)

所定の位置に

関数への引数を変更したい場合は、それらをポインターとして渡すことができます。たとえば、この関数は両方の引数をインクリメントしてから、それらの合計を返します。

int increment_and_sum(int* a, int* b) {
     (*a)++;
     (*b)++;
     return a + b
}

あなたは次のように使用します:

int a = 10, b = 3, sum;
sum = increment_and_sum(&a, &b);
// a == 11, b == 4, sum == 15

(でリテラルを使用できないことに注意してください。つまり、またはを使用increment_and_sumすることはできません。)increment_and_sum(3, 4)increment_and_sum(&3, &4)

于 2012-04-22T02:38:37.997 に答える
5

値がすべて論理的に関連している場合、それらを構造体に入れることは理にかなっています。ただし、密結合されていないいくつかの値のみを変更する場合は、次のようにポインターとして渡すことができます。

int swap(int *a, int *b) {
  int tmp;

  if (a == b) { // Pointers are equal, so there's nothing to do!
    return -1;  // Indicate the values haven't changed.
  }

  tmp = *a;
  *a = *b;
  *b = tmp;
  return 0;  // Indicate the swap was successful.
}

void main(...) {
  int first = 12;
  int second = 34;

  if (swap(&first, &second) == -1) {
    printf("Didn't swap: %d, %\n", first, second);
  } else {
    printf("Swapped: %d, %d\n", first, second);
  }
}

データを関数の引数に入れ、関数が成功/失敗、またはその他の状態を示す値を返すようにすることは、かなり標準的な手法です。\

于 2012-04-22T02:28:19.977 に答える
2

ポインターを変数に渡してメソッドに設定する必要はありません。そのようです:

void get_some_values()
{
    int a=0, b=0, c=0;
    compute(&a, &b, &c);

    // after call to compute a=1, b=2, c=3;
}

void compute(int *a, int *b, int c*)
{
    *a = 1;
    *b = 2;
    *c = 3;
}
于 2012-04-22T02:30:11.847 に答える
2

これを行う通常の方法は、ポインター引数を使用することです。変数の個数を返す必要がある場合は、データへのポインタと整数の「個数」へのポインタを使用できます。それを行う別の方法は、ポインターからポインターであり、必要に応じて関数にメモリを割り当てさせます。これにより、呼び出し元がそれを解放する責任を負います。

例:

int make_numbers(int **numbers, int *count)
{
  /* work out how many numbers we want to generate */
  *count = howmany;
  *numbers = malloc(*count * sizeof(int));
  /* fill *numbers array here */
  return 0; /* success */
}

void caller(void)
{
  int *numbers;
  int count;
  if (0 == make_numbers(&numbers, &count)) {
    /* use the numbers */
    free(numbers);
  }
}
于 2012-04-22T02:36:05.157 に答える
1

技術的に言えば、関数は 1 つの値のみを返します。そうでなければ、それは関数ではありません (数学関数を覚えていますか? ここでも同じ原理です)。

あなたができることは次のとおりです。

  • それらを構造体に配置し、要素が関連している場合は構造体を返します。おそらくこれを行うための最も簡単で明確な方法です。
  • それらを配列に配置し、配列を返します。構造体と同じくらい簡単ですが、明確ではないかもしれません。
  • (数値のみ) 一種の自己設計マップを使用して、それらを 1 つの整数 (a = 100 * a、b = 10 * b、c = c) にすることができます。

配列を含む例:

int* coords(int x, int y) {
    int *a = calloc(sizeof(int), 2);
    a[0] = x;
    a[1] = y;
    return a;
} 

int main() {

    int* vals = coords(47, -121);
    printf("vals = {%d, %d}\n", vals[0], vals[1]);
    return 0;
}

vals = {47, -121}
于 2012-04-22T02:31:24.237 に答える
0

ポインターを使用して配列を返すこともできます。ここではデモンストレーションを示します。 http://www.tutorialspoint.com/cprogramming/c_return_arrays_from_function.htm

于 2015-11-14T18:28:26.667 に答える
0

いいえ、できませんが、よりC++っぽい別の代替ソリューションは、構造体を作成してから返すことです。

    struct RET_TYPE
    {
        int a;
        int b;
    };

    struct RET_TYPE foo()
    {
         ...

         return RET_TYPE();
    }
于 2012-04-22T02:31:00.867 に答える
-1

構造体が必要ない場合は、参照渡しのみが可能です。適切なドキュメント、おそらく宣言型プログラミングが必要です。

void compute(int& a, int& b, int& c) { ... }
void compute(int* a, int* b, int* c) { ... }
于 2012-04-22T02:30:53.410 に答える