【问题标题】:How would I shorten these for loops?我将如何缩短这些 for 循环?
【发布时间】:2016-10-06 21:48:57
【问题描述】:

所以我有一个程序可以运行 0000000000 和 ZZZZZZZZZZ 之间所有可能的字母数字组合。目前我正在使用此代码:

for (digit[0] = 0; digit[0] < 36; digit[0]++)
    for (digit[1] = 0; digit[1] < 36; digit[1]++)
        for (digit[2] = 0; digit[2] < 36; digit[2]++)
            // etc...

...最终有 10 个嵌套的 for 循环,我的整个编辑器屏幕都被填满了。那么我如何将它压缩成一两个 for 循环呢?我不知道如何将它们放在一起测试和递增digit[i]。提前感谢任何拥有此解决方案的人。我敢打赌这方面的网页有一百万个,但我想不出如何在谷歌搜索中表达它。

【问题讨论】:

  • 您确实意识到涉及的组合数量使得这不切实际
  • @OlegAndriyanov 是的,这需要很长时间,这就是我需要更好方法的原因之一

标签: c for-loop increment


【解决方案1】:

使用里程表算法。增加最后一位。当它达到最大值时,将其包装回0 并对剩余的数字进行递归,直到用完数字为止。

int increment_digit(int array[], unsigned int index, limit) {
    if (index == -1) { // We've wrapped around the entire set
        return 0;
    }
    array[index]++;
    if (array[index] == limit) {
        array[index] = 0;
        return increment_digit(array, index-1, limit);
    } else {
        return 1;
}

int main(int argc, char **argv) {
    int digits[SIZE] = {0};
    while (1) {
        // do stuff ...
        if (!increment_digit(digits, SIZE-1, 36))
            break;
        }
    }
    return 0;
}

【讨论】:

  • 初始调用应该是SIZE-1
  • 我做了一个打印数字或字母的函数。我应该在这段代码的哪里添加它?
【解决方案2】:

这是一种使用递归函数的解决方案。你可能需要稍微调整一下,因为我不得不假设一些事情——比如你正在使用的数组的类型。

另外,请注意,如果 for 循环运行太多次,这将溢出。

void incDigit(int *digits) {
  digits[0]++;
  if(digits[0] >= 36) {
    digits[0] = 0;
    incDigit(digits + 1);
  }
}

int digits[10];
int i, j;
for(i = 0; i < (int)pow(36, 5); i++) {
  for(i = 0; i < (int)pow(36, 5); i++) {
    //Code here  
    incDigit(digits);
  }
}

【讨论】:

  • 您的 for() 循环在 32 位系统上不起作用,因为 pow(36,10) 大于 MAX_INT,所以 i &lt; pow(36,10) 将始终为真。
  • @Barmar 有趣的点。 pow 返回 double。 AFAIK 将intdouble 进行比较时,第一个将被转换为double。因此,在将int 转换为double 时,由于精度损失,更有可能出现一些冗余(或缺失)迭代。
  • 最终i 将达到MAX_INT,然后下一次迭代将执行i++,您将得到i 的溢出。
  • 这就是为什么我的答案让递归函数返回一个布尔值,指示它何时完全环绕。
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2019-02-27
  • 2022-11-01
  • 2011-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多