I'm trying to figure out a simple way to handle dynamic nested loops level. Consider the following function that takes in 2 parameters: #num of loops, and max value.
void PrintLoop(int maxloop, int maxvalue)
PrintLoop(1,2);
// output
0
1
PrintLoop(2,2);
// output
0, 0
0, 1
1, 0
1, 1开发者_C百科
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...
Is there a way to write a function that can generate this "dynamic nested loops" behavior?
Thanks for any help
Yes, it is possible, and to implement this a concept of "recursion" is often used:
void PrintLoop(int maxloop, int maxvalue)
{
if (maxloop<=0) return ;
// print something here...
for (int i=0;i<maxvalue;i++){
PrintLoop(maxloop-1, maxvalue);
// After Recursion do something here...
}
}
Pavel's answer shows how to perform recursion. However, a function which takes only two arguments (number of loops and maximum value) does not have enough context to actually print the numbers as in your example. For that, you'll have to keep track of some extra information. One way to do this, is the following:
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);
}
Now print_loop(3, 2)
behaves as expected.
Edit: actually, one can write a two-argument function to do this, through the use of static
variables which are initialized upon receiving a positive width
argument. After this initialisation stage the function then performs its recursion using negative values. Obviously, the resulting code is horrible, but I'll post it anyway, for the sake of completeness:
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);
}
}
}
You can use recursion or you can explicitly store each loop's state and manage the states in a single loop.
In this case it means storing an array of counters. Each execution of the main loop advances the innermost counter and all outer counters whose inner neighbours 'carry over'. The highest counter acts as a guard.
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
}
}
In Ada you could do a DECLARE block after getting the user input; then set your loop to go from 1 .. Read_In_Loop_Control_Value and then a nested loop to print integers from 1 .. Read_In_Number_Per_Line value.
精彩评论