动态嵌套循环级别

Vu *_*Duy 6 c algorithm

我试图找出一种处理动态嵌套循环级别的简单方法.考虑以下函数,它接受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)

等等...

有没有办法编写一个可以生成这种"动态嵌套循环"行为的函数?

谢谢你的帮助

P S*_*ved 9

是的,这是可能的,并且为了实现这一点,经常使用" 递归 " 的概念:

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)


Ste*_*202 5

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)


Raf*_*ird 5

您可以使用递归,也可以显式存储每个循环的状态并在单个循环中管理状态。

在这种情况下,这意味着存储一个计数器数组。主循环的每次执行都会使最里面的计数器及其内部邻居“结转”的所有外部计数器前进。最高的柜台充当警卫。

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)