【问题标题】:Dynamic nested loops level动态嵌套循环级别
【发布时间】:2009-11-15 11:26:00
【问题描述】:

我正在尝试找出一种处理动态嵌套循环级别的简单方法。考虑以下接受 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

等等……

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

感谢您的帮助

【问题讨论】:

  • 给定函数PrintLoop(m,n),观察你所做的只是在基数n中从0计数到n^m
  • 这看起来很像家庭作业,到目前为止你尝试过什么代码,你还在坚持什么?

标签: c algorithm


【解决方案1】:

是的,这是可能的,为了实现这一点,经常使用“recursion”的概念:

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

【讨论】:

  • 嗯,递归是实现这一点的一种手段,而不是概念的名称。
  • @Stephan202,当然,我可以写这些陈述,但有件事告诉我,这是一个家庭作业,所以我最好坚持提供一般性建议......
  • @PavelShved 的答案不起作用,我有自己的类似功能,只是“maxvalue”和“maxloop”的顺序相反。对于 (3,2) 的情况,我只得到 7 次迭代,而我应该得到 8 次迭代,因为 2 的 3 = 8 次方
【解决方案2】:

Pavel's answer 展示了如何执行递归。但是,仅采用两个参数(循环数和最大值)的函数没有足够的上下文来实际打印您的示例中的数字。为此,您必须跟踪一些额外的信息。一种方法如下:

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

现在print_loop(3, 2) 的行为符合预期。

编辑:实际上,一个可以编写一个有两个参数的函数来做到这一点,通过使用static变量,这些变量在收到一个肯定的@987654325时被初始化@ 争论。在这个初始化阶段之后,函数然后使用负值执行其递归。显然,生成的代码很糟糕,但为了完整起见,我还是会发布它:

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】:

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

在这种情况下,它意味着存储一个计数器数组。主循环的每次执行都会推进最内层的计数器和其内邻“结转”的所有外层计数器。最高的柜台充当守卫。

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】:

    在 Ada 中,您可以在获得用户输入后执行 DECLARE 块;然后将循环设置为从 1 .. Read_In_Loop_Control_Value 开始,然后设置一个嵌套循环以打印从 1 .. Read_In_Number_Per_Line 值开始的整数。

    【讨论】:

      猜你喜欢
      • 2011-02-01
      • 2012-03-09
      • 2015-05-24
      • 2021-01-15
      • 2016-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-01
      相关资源
      最近更新 更多