我试图找出一种处理动态嵌套循环级别的简单方法.考虑以下函数,它接受2个参数:#num of loops和max value.
void PrintLoop(int maxloop, int maxvalue)
PrintLoop(1,2);
// output
0
1
PrintLoop(2,2);
// output
0, 0
0, 1
1, 0
1, 1
PrintLoop(3,2);
// output
0, 0, 0
0, 0, 1
0, 1, 0
0, 1, 1
1, 0, 0
1, 0, 1
1, 1, 0
1, 1, 1
Run Code Online (Sandbox Code Playgroud)
等等...
有没有办法编写一个可以生成这种"动态嵌套循环"行为的函数?
谢谢你的帮助
是的,这是可能的,并且为了实现这一点,经常使用" 递归 " 的概念:
void PrintLoop(int maxloop, int maxvalue)
{
if (maxloop<=0) return ;
// print something here...
for (int i=0;i<maxmalue;i++){
PrintLoop(maxloop-1, maxvalue);
}
}
Run Code Online (Sandbox Code Playgroud)
Pavel的答案显示了如何执行递归.但是,只有两个参数(循环数和最大值)的函数没有足够的上下文来实际打印数字,如示例所示.为此,您必须跟踪一些额外信息.一种方法是:
void _print_loop(int *values, int width, int cur_col, int max) {
if (cur_col == width) {
for (int i = 0; i < width; i++) {
printf("%d%c", values[i], (i < width - 1) ? ' ' : '\n');
}
} else {
for (int i = 0; i < max; i++) {
values[cur_col] = i;
_print_loop(values, width, cur_col + 1, max);
}
}
}
void print_loop(int width, int max) {
int values[width];
memset(values, 0, width * sizeof(int));
_print_loop(values, width, 0, max);
}
Run Code Online (Sandbox Code Playgroud)
现在print_loop(3, 2)表现得像预期的那样.
编辑:实际上,通过使用在接收到正参数时初始化的变量,可以编写一个双参数函数来执行此操作.在此初始化阶段之后,函数然后使用负值执行其递归.显然,生成的代码很糟糕,但为了完整起见,我还是会发布它:staticwidth
void print_loop(int width, int max) {
static int max_width;
static int *values;
if (width > 0) {
max_width = width;
if ((values = calloc(width, sizeof(int))) == NULL) {
perror("calloc");
exit(EXIT_FAILURE);
}
print_loop(-width, max);
free(values);
}
else if (width == 0) {
for (int i = 0; i < max_width; i++) {
printf("%d%c", values[i], (i < max_width - 1) ? ' ' : '\n');
}
}
else {
for (int i = 0; i < max; i++) {
values[-width - 1] = i;
print_loop(width + 1, max);
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以使用递归,也可以显式存储每个循环的状态并在单个循环中管理状态。
在这种情况下,这意味着存储一个计数器数组。主循环的每次执行都会使最里面的计数器及其内部邻居“结转”的所有外部计数器前进。最高的柜台充当警卫。
void printloop(int maxloop, int maxvalue) {
unsigned int counters[maxloop+1]; // C99 for the win
memset(counters, 0, sizeof(counters));
while(!counters[maxloop]) {
int i;
char *sep="";
for(i=maxloop; i-->0;) {
printf("%s%d",sep,counters[i]);
sep=",";
};
printf("\n");
for(i=0; counters[i]==maxvalue; i++) // inner loops that are at maxval restart at zero
counters[i]=0;
++counters[i]; // the innermost loop that isn't yet at maxval, advances by 1
}
}
Run Code Online (Sandbox Code Playgroud)