在 C 中,如何编写 N 是可变的 N 维嵌套 for 循环
In C, how to write a N-dimensional nested for loop where N is variable
我需要写声明:
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 )
怎么做?
你可以写一个递归函数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);
如果您需要做的是真正的变量 N,那么 Patrick 的递归方法是一种可行的方法。
如果您尝试做的是固定变量N并且您试图避免重复输入for循环,您可以使用宏来保存一些击键:
#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
}
可以将N维space表示为1维,有一个索引,如果需要可以从中计算出N个子索引。
下面我附上了这种 space 扁平化
的示例实现
#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;
}
bonds/sizes 数组的动态处理超出了此处的范围。该示例显示了如何从展平 space.
计算子索引
我需要写声明:
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 )
怎么做?
你可以写一个递归函数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);
如果您需要做的是真正的变量 N,那么 Patrick 的递归方法是一种可行的方法。
如果您尝试做的是固定变量N并且您试图避免重复输入for循环,您可以使用宏来保存一些击键:
#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
}
可以将N维space表示为1维,有一个索引,如果需要可以从中计算出N个子索引。
下面我附上了这种 space 扁平化
的示例实现#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;
}
bonds/sizes 数组的动态处理超出了此处的范围。该示例显示了如何从展平 space.
计算子索引