Dynamic nested loops level

﹥>﹥吖頭↗ 提交于 2021-02-07 13:35:40

问题


I'm trying to figure out a simple way to handle dynamic nested loops level. Consider the following function that takes in 2 parameters: #num of loops, and 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

Etc...

Is there a way to write a function that can generate this "dynamic nested loops" behavior?

Thanks for any help


回答1:


Yes, it is possible, and to implement this a concept of "recursion" is often used:

void PrintLoop(int maxloop, int maxvalue)
{
   if (maxloop<=0) return ;
   // print something here...
   for (int i=0;i<maxvalue;i++){
      PrintLoop(maxloop-1, maxvalue);
      // After Recursion do something here...
   }
}



回答2:


Pavel's answer shows how to perform recursion. However, a function which takes only two arguments (number of loops and maximum value) does not have enough context to actually print the numbers as in your example. For that, you'll have to keep track of some extra information. One way to do this, is the following:

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);
}

Now print_loop(3, 2) behaves as expected.

Edit: actually, one can write a two-argument function to do this, through the use of static variables which are initialized upon receiving a positive width argument. After this initialisation stage the function then performs its recursion using negative values. Obviously, the resulting code is horrible, but I'll post it anyway, for the sake of completeness:

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);
    }   
  }
}



回答3:


You can use recursion or you can explicitly store each loop's state and manage the states in a single loop.

In this case it means storing an array of counters. Each execution of the main loop advances the innermost counter and all outer counters whose inner neighbours 'carry over'. The highest counter acts as a guard.

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
    }
}



回答4:


In Ada you could do a DECLARE block after getting the user input; then set your loop to go from 1 .. Read_In_Loop_Control_Value and then a nested loop to print integers from 1 .. Read_In_Number_Per_Line value.



来源:https://stackoverflow.com/questions/1737289/dynamic-nested-loops-level

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!