c - 在 C 运行时生成嵌套循环

标签 c loops for-loop while-loop nested

我知道使用递归方式,但它仅适用于循环,其开始和结束语句与下面的代码相同

for (int i=1 ; i<5;i++){
    for (int j=0; j<5;j++){
       for (int m= 0;m<5;m++) {
           // N time
       }
    }
}

但我的问题不同。我不知道编译时的 N 层以及开始和结束语句。我将在运行时向用户学习它们。

喜欢:

for (int i=1 ; i<5;i++){
        for (int j=5; j<18;j++){
           for (int m= 4;m<5;m++) {
               // N time
           }
        }
    }

所以我的问题是:有没有办法在编译时不知道 N 的情况下创建嵌套的 N 级 for 循环?

最佳答案

您可以通过构造一些数据来充当迭代器并将其视为迭代的单个事物来实现此目的。该数据将为您希望迭代的每个维度包含一个单独的计数器,并且它将由本身在每个维度上迭代的函数进行初始化、测试和递增。下面是一个使用简单数组作为计数器的示例。

#include <string.h>


//  Initialize counters to their start values.
static void InitializeCounters(long N, long *Counters, const long *Starts)
{
    memcpy(Counters, Starts, N * sizeof *Counters);
}


//  Return 1 if there are more values to iterate, 0 otherwise.
static int MoreToIterate(long N, long *Counters, const long *Ends)
{
    return Counters[0] < Ends[0];
}


//  Increment the counters, lexicographic (dictionary/odometer) style.
static void IncrementCounters(long N, long *Counters, const long *Starts,
    const long *Ends)
{
    /*  Increment each dimension (except the first will be special).  If it
        rolls over its end, reset it to its start and go on the next dimension.
        If it does not roll over, stop there.
    */
    for (long i = N-1; 0 < i; --i)
        if (++Counters[i] < Ends[i])
            return;
        else
            Counters[i] = Starts[i];

    /*  For dimension zero, do not reset it, so MoreToIterate can see it
        finished.
    */
    ++Counters[0];
}


#include <stdio.h>
#include <stdlib.h>


static void _Noreturn Usage(char *argv[])
{
    fprintf(stderr, "Usage: %s <N>\n", argv[0]);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    if (argc != 2)
        Usage(argv);

    char *end;
    long N = strtol(argv[1], &end, 0);
    if (*end != '\0')
        Usage(argv);

    if (N < 0)
        Usage(argv);

    long *Counters = malloc(N * sizeof *Counters);
    long *Starts   = malloc(N * sizeof *Starts);
    long *Ends     = malloc(N * sizeof *Ends);
    if (!Counters || !Starts || !Ends)
    {
        fprintf(stderr, "Error, unable to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    //  Initialize start and end values as desired.
    for (long i = 0; i < N; ++i)
    {
        Starts[i] = 0;
        Ends[i]   = i+1;
    }

    for (   InitializeCounters(N, Counters, Starts);
            MoreToIterate(N, Counters, Ends);
            IncrementCounters(N, Counters, Starts, Ends))
    {
        for (long i = 0; i < N; ++i)
            printf("%ld ", Counters[i]);
        printf("\n");
    }

    free(Ends);
    free(Starts);
    free(Counters);
}

使用参数“3”执行时的示例输出为:

0 0 0 
0 0 1 
0 0 2 
0 1 0 
0 1 1 
0 1 2 

关于c - 在 C 运行时生成嵌套循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60708989/

相关文章:

c++ - 如何绘制到控制台/终端的某个部分?

c - 在c中制作共享数据结构

javascript - For In循环,为什么无法通过obj.property访问属性值?

c - 正在检查编译器优化的循环中的复杂表达式?

python - 为什么 "j"能够识别范围变化,而 "i"却不能?

c++ - 对于不可复制类型的范围循环,是否可能?

linux - 在 bash 中订购一个循环

c - sizeof(enum) == sizeof(int) 总是这样吗?

c - C 中的 R 包依赖于另一个 R 包

javascript - Angular JS - 从重复中变得更大