2009-11-15 88 views
6

我想弄清楚一個簡單的方法來處理動態嵌套循環級別。考慮下面的函數需要2個參數:#num循環和最大值。動態嵌套循環級別

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 

等...

有沒有編寫能夠產生這種「動態嵌套循環」的行爲函數的方法嗎?

感謝所有幫助

+3

給定'PrintLoop(m,n)'函數,注意你所做的所有操作都是從基數'n'中的0到'n^m'。 – 2009-11-15 11:47:49

+0

這看起來很像一個家庭作業,到目前爲止你已經嘗試了哪些代碼,以及你堅持了什麼? – mlibby 2009-11-15 13:27:31

回答

9

是的,這是可能的,併爲此實施的「recursion」概念經常被用來:

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

那麼,遞歸是實現這一點的*手段*,而不是概念的名稱。 – 2009-11-15 11:36:38

+0

遞歸是要走的路,是的。但我錯過了任何印刷聲明...... – Stephan202 2009-11-15 11:37:49

+1

@ Stephan202,當然,我*可以*寫出這些陳述,但是有些東西告訴我,這是一項家庭作業,所以我最好堅持提供一般建議...... – 2009-11-16 08:34:47

0

在阿達你可以做一個DECLARE塊獲取後用戶輸入;然後將您的循環設置爲1 .. Read_In_Loop_Control_Value,然後使用嵌套循環從1 .. Read_In_Number_Per_Line值打印整數。

5

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變量這是在得到肯定的width參數初始化。在此初始化階段之後,該函數然後使用負值執行其遞歸。顯然,生成的代碼是可怕的,但無論如何,我會張貼,爲了完整起見:

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

感謝您的詳細解答。我預計這個問題必須通過遞歸來解決。 雖然,我希望有一種機制可以純粹使用迭代。編程語言需要一些更新:) – 2009-11-15 20:45:07

+0

有*是一個非常簡單的方法來做到這一點,而不使用遞歸。看到我對你原來的問題的評論。 – 2009-11-16 22:31:08

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