在 C 语言中在运行时生成嵌套循环 [英] Generating Nested Loops at Run Time in C

查看:19
本文介绍了在 C 语言中在运行时生成嵌套循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

但我的问题不同.我在编译时不知道 N 级和开始和结束语句.我将在运行时向用户学习.

喜欢:

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

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

解决方案

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

#include //将计数器初始化为其起始值.static void InitializeCounters(long N, long *Counters, const long *Starts){memcpy(Counters, Starts, N * sizeof *Counters);}//如果要迭代的值更多,则返回 1,否则返回 0.static int MoreToIterate(long N, long *Counters, const long *Ends){返回计数器 [0] <结束[0];}//增加计数器,字典(字典/里程表)样式.static void IncrementCounters(long N, long *Counters, const long *Starts,const long *Ends){/* 增加每个维度(除了第一个是特殊的).如果它翻过它的末端,将它重置到它的起点,然后进入下一个维度.如果它没有翻滚,就停在那里.*/for (long i = N-1; 0 < i; --i)if (++Counters[i] < Ends[i])返回;别的计数器[i] = 开始[i];/* 对于维度零,不要重置它,所以 MoreToIterate 可以看到它完成的.*/++计数器[0];}#include #include 静态无效_Noreturn 用法(char *argv[]){fprintf(stderr, "用法: %s 
", argv[0]);退出(EXIT_FAILURE);}int main(int argc, char *argv[]){如果(argc!= 2)用法(argv);字符 * 结束;long N = strtol(argv[1], &end, 0);if (*end != '')用法(argv);如果 (N <0)用法(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, "错误,无法分配内存.
");退出(EXIT_FAILURE);}//根据需要初始化开始值和结束值.for (long i = 0; i 

使用参数3"执行时的示例输出是:

<前>0 0 00 0 10 0 20 1 00 1 10 1 2

I know using recursions way but it works just for loops which beginning and ending statements are same like code below

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

But my problem is different. I do not know N level and beginning and ending statements at compile time. I will learn them from user at Run Time.

Like:

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

So my question is : Is there a way to create nested N level for loop without knowing N at compile time?

解决方案

You can do this by constructing some data to act as an iterator and treating it as a single thing that is iterated. That data will contain a separate counter for each dimension you wish to iterate, and it will be initialized, tested, and incremented by functions that themselves iterate over each dimension. Here is an example using a simple array for the counters.

#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>
", 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 != '')
        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.
");
        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("
");
    }

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

Sample output when executed with argument "3" is:

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

这篇关于在 C 语言中在运行时生成嵌套循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆