在C中,如何编写N维嵌套for循环,其中N是可变的

时间:2018-02-06 22:47:41

标签: c nested-loops n-dimensional

我需要写下声明:

for ( int i1 = i1_min; i1 < width; ++i1 )
    for ( int i2 = i2_min; i2 < i2_max; ++i2 )
        for ( int i3 = i3_min; i3 < i3_max; ++i3 )
            ...
                for ( int iN = iN_min; iN < iN_max; ++iN )

怎么做?

3 个答案:

答案 0 :(得分:5)

您可以编写递归函数loopn()来执行此操作:

void loopn_recurse (int *min, int *max, int *counters, size_t N, size_t n, void (*func)(int*, size_t)) {
  for (int i = min[n]; i < max[n]; ++i) {
    counters[n] = i;

    if (N - n > 1) {
      loopn_recurse(min, max, counters, N, n + 1, func);
    } else {
      // innermost algorithm
      func(counters, N);
    }
  }
}

void loopn (int *min, int *max, int *counters, size_t N, void (*func)(int*, size_t)) {
  assert(N > 0);
  loopn_recurse(min, max, counters, N, 0, func);
}

// example usage

void test (int *counters, size_t N) {
  for (size_t j = 0; j < N; ++j) {
    printf("%d ", counters[j]);
  }

  putchar('\n');
}

loopn((int[]){ 1, 2, 3, 4, 5 }, (int[]){ 2, 4, 6, 8, 10 }, (int[5]){}, 5, test);

Try it online!

答案 1 :(得分:1)

可以将N维空间表示为1维,具有一个索引,如果需要,可以从中计算N个子索引。

下面我附上这种空间展平的示例实现

#include <stdio.h>

int bonds[][2] = {
  {1, 2},
  {5, 10},
  {0, 3},
  {6, 8}
};

int get_index(int index_position, int current, int sizes[], int sizes_size) {
  int mod = 1;
  for(int i = index_position; i < sizes_size; i++) {
    mod *= sizes[i];
  }

  int div = mod / sizes[index_position];

  return (current % mod) / div;
}

int main(int argc, char** argv) {

  int sizes[] = {
    bonds[0][1] - bonds[0][0],
    bonds[1][1] - bonds[1][0],
    bonds[2][1] - bonds[2][0],
    bonds[3][1] - bonds[3][0]
  };

  int big_size = sizes[0] * sizes[1] * sizes[2] * sizes[3];

  for(int i = 0; i < big_size; i++) {
    /* get indexes */

    /*
    int i0 = ((i % (sizes[0] * sizes[1] * sizes[2] * sizes[3])) / (sizes[1] * sizes[2] * sizes[3])) + bonds[0][0];
    int i1 = ((i % (           sizes[1] * sizes[2] * sizes[3])) / (           sizes[2] * sizes[3])) + bonds[1][0];
    int i2 = ((i % (                      sizes[2] * sizes[3])) / (                      sizes[3])) + bonds[2][0];
    int i3 = ((i % (                                 sizes[3]))                                   ) + bonds[3][0];
    */

    int i0 = get_index(0, i, sizes, 4) + bonds[0][0];
    int i1 = get_index(1, i, sizes, 4) + bonds[1][0];
    int i2 = get_index(2, i, sizes, 4) + bonds[2][0];
    int i3 = get_index(3, i, sizes, 4) + bonds[3][0];

    printf("%d %d %d %d\n", i0, i1, i2, i3);
  }

  return 0;
}

债券/尺寸数组的动态处理超出了范围。该示例显示了如何从展平空间计算子索引。

答案 2 :(得分:0)

如果你需要做的是真正变量N,那么帕特里克的递归就是一种方法。

如果你尝试做的是修复变量N并且你试图避免重复键入循环,你可以使用宏来保存一些键击:

#define LOOP(N) for (int i#N = i#N#_min; i#N < i#N#_max; ++i#N )

LOOP(1)
LOOP(2)
LOOP(3)
LOOP(4)
LOOP(5) {
   val = i1+i2+i3+i4+i5; // example calculation
}