2009-11-15 16 views
6

Sto provando a capire un modo semplice per gestire il livello dei cicli nidificati dinamici. Si consideri la seguente funzione che accetta 2 parametri: #num of loops e valore massimo.Livello loop dinamico nidificato

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 

Etc ...

C'è un modo per scrivere una funzione che può generare questo comportamento "dinamici cicli annidati"?

Grazie per qualsiasi aiuto

+3

Data la funzione 'PrintLoop (m, n)', osserva che tutto ciò che fai è contare da 0 a 'n^m' in base' n'. –

+0

Sembra molto simile a un compito a casa, quale codice hai provato finora e su cosa sei bloccato? – mlibby

risposta

9

Sì, è possibile, e ad attuare questo un concetto di "recursion" è spesso usato:

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

Bene, la ricorsione è un * significa * per implementare questo, non il nome del concetto. –

+0

La ricorsione è la strada da percorrere, sì. Ma mi mancano le dichiarazioni di stampa ... – Stephan202

+1

@ Stephan202, naturalmente, io * potrei * scrivere le dichiarazioni, ma qualcosa mi dice, che è un compito a casa, quindi mi conviene attenermi a dare un consiglio generale ... –

0

In Ada si potrebbe fare un blocco declare dopo avere ottenuto il input dell'utente; quindi imposta il loop in modo che passi da 1 .. Read_In_Loop_Control_Value e quindi un ciclo nidificato per stampare numeri interi da 1 .. Read_In_Number_Per_Line valore.

5

Pavel's answer mostra come eseguire la ricorsione. Tuttavia, una funzione che richiede solo due argomenti (numero di cicli e valore massimo) non ha un contesto sufficiente per stampare effettivamente i numeri come nell'esempio. Per questo, dovrai tenere traccia di alcune informazioni extra. Un modo per fare questo, è il seguente:

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

ora print_loop(3, 2) si comporta come previsto.

Edit: realtà, si può scrivere una funzione due argomenti per fare questo, attraverso l'uso di static variabili che vengono inizializzati alla ricezione di un width argomento positivo. Dopo questa fase di inizializzazione, la funzione esegue la ricorsione utilizzando valori negativi. Ovviamente, il codice risultante è orribile, ma io post it in ogni caso, per ragioni di completezza:

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

Grazie per la tua risposta dettagliata. Mi aspettavo che questo problema dovesse essere risolto usando le ricorsioni. Anche se speravo che potesse esserci un meccanismo per farlo usando esclusivamente iterazioni.I linguaggi di programmazione necessitano di qualche aggiornamento :) –

+0

Ci * è * un modo abbastanza semplice per farlo senza ricorrere alla ricorsione. Vedi il mio commento alla tua domanda originale. –

3

È possibile utilizzare la ricorsione o si può esplicitamente memorizzare lo stato di ogni ciclo e gestire gli stati in un singolo ciclo.

In questo caso significa memorizzare una serie di contatori. Ogni esecuzione del ciclo principale fa avanzare il contatore più interno e tutti i segnalini esterni i cui vicini interni "trasporta". Il contatore più alto funge da guardia.

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