Pseudo-coding an N-iterative loop

I am currently needing to create a loop that deals with N iterators. The real purpose is to create a series of names which will then be used to open files with such names. But anyways...

For example, imagine you have an input such as
A%B%C% (1 2 3) (4 5) (6)


The program should then create the following names:
A1B4C6
A1B5C6
A2B4C6
A2B5C6
A3B4C6
A3B5C6


That is, the % is a placeholder for the values in each parentheses.

In this case, the best loop would be (in pseudo-code)
1
2
3
4
for (each A)
   for(each B)
      for(each C)
         CreateName();


However, that is hard-written as a three-iterator loop. What if the filename is only "A%B%"? What if it's a crazy "A%B%C%D%E%F%G%"?

I've tried writing something like
1
2
3
4
for(each position)
   for(each position after this position)
      for(each value of the position)
         CreateName();


But it doesn't seem to work. To keep things a bit more realistic, here's my actual code:

1
2
3
4
5
6
7
8
9
10
11
12
13
for(i=count-2;i>=0;i--)
{
	for(int j=count-1;j>i;j--)
	{
		stringstream _substr(substr[j]);
		string value;
		while(_substr >> value)
		{
			name.replace(pos[j],1,value);
			cout << name << endl;
		}
	}
}

Where substr contains all the values of each parentheses ( 1 2 3 and 4 5 and 6 in different strings) and name contains the "first value" (A1B4C6)

However, this doesn't work. It loops too much in the beginning, repeating itself, and loops too little in the end.
Here's something:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>

template<int N>
struct iterator{
    iterator<N>* max;
    int val[N];

    iterator() : max(0){
        memset(val, 0, N*sizeof(int));
    }
    bool operator ++(){
        if(!max) return 0;
        val[0]++;
        for(int i = 0; i < N; i++){
            if(val[i] >= max->val[i]){
                if(i < N-1){
                    val[i+1]++;
                    val[i] = 0;
                }else return 0;
            };
        }
        return 1;
    }
};

int main(){
    iterator<3> max;
    max.val[0] = 2;
    max.val[1] = 5;
    max.val[2] = 3;

    iterator<3> i;
    i.max = &max;

    do{
        std::cout << "A" << i.val[0] << "B" << i.val[1] << "C" << i.val[2] << '\n';
    }while(++i);
    std::cin.get();
    return 0;
}

You could make it more flexible: with non constant size, minimum values, and so on, but I'm a little too lazy for that.
Here is a quick implementation. Remember, I have not done any error checking & the solution uses recursion. The crux of the implementation is in the replace recursive method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <sstream>
using namespace std;

void replace(const string& s, vector<vector<char> >& vreps, int index);

int main()
{
	string sInput = "A%B%C% (1 2 3) (4 5) (6)", sToken;
	cout << "Input: " << sInput << endl;
	vector<string> vs;

	// Tokenize string
	// A%B%C%
	// 1 2 3
	// 4 5
	// 6

	string::size_type fpos = sInput.find(" ("), spos = 0;
	while (fpos != string::npos){
		if (sInput[fpos - 1] == ')')
			sToken = sInput.substr(spos, fpos - spos - 1);
		else
			sToken = sInput.substr(spos, fpos - spos);
			
		vs.push_back(sToken);
		spos = fpos + 2;
		fpos = sInput.find(" (", spos);
	}
	if (spos < sInput.size())
		vs.push_back(sInput.substr(spos, sInput.size() - spos - 1));
	
	// Create the replacement vector which is a vector of vector of chars with the replacement values

	vector<vector<char> > vreps(vs.size()-1);
	for (vector<string>::size_type i = 1; i < vs.size(); ++i){
		istringstream ss(vs[i]);
		char c;
		while (ss >> c){
			vreps[i-1].push_back(c);
		}
	}

	// Invoke replace with A%B%C% & the replacement vector
	cout << "Output: " << endl;
	replace(vs[0], vreps, 0);
}

void replace(const string& s, vector<vector<char> >& vreps, int index)
{
	string sTmp = s;
	string::size_type fpos = s.find("%");
	if (fpos != string::npos){
		for (vector<vector<char> >::size_type i=0; i < vreps[index].size(); ++i){
			sTmp.replace(fpos, 1, string(1, vreps[index][i]));
			replace(sTmp, vreps, index + 1); // Recursive call to replace
		}		
	}
	else
		cout << s << endl;
}
Many thanks naivnomore, that worked like a charm. I had to make a few alterations to make it error-safe (in case the user didn't input all the variables or if there were no variables, for example) but that worked out amazingly well.
Topic archived. No new replies allowed.