For starters, this is definitely not a case for a nested loop. In fact,
your entire code boils down to:
pass = initialPattern();
while ( isValidPattern( pass ) ) {
nextPattern( pass );
std::cout << pass << std::endl;
}
(But I wonder if you don't really mean to do the output before the
increment.)
Now all you have to do is define the type of pass and relevant
functions; you might even consider
putting everything in a class, since all of the functions operate on the
same data instance.
Judging from your code, pass should be an std::string with 8
characters; the initialization could be written:
std::string pass( 8, 'A' );
isValidPattern apparently only looks at the first character. (I'm not
sure that's correct, but that's what your code does.) Something like:
bool
isValidPattern( std::string const& pattern )
{
return pattern[0] != '[';
}
according to your code, but something like:
struct NotIsUpper
{
bool operator()( char ch ) const
{
return ! ::isupper( static_cast<unsigned char>( ch ) );
}
};
bool
isValidPattern( std::string const& pattern )
{
return pattern.size() == 8
&& std::find_if( pattern.begin(), pattern.end(), NotIsUpper() )
== pattern.end();
}
would seem more appropriate. (Of course, if you're doing any sort of
coding with text, you'd already have NotIsUpper and its siblings in
your tool kit.)
Finally, nextPattern seems to be nothing more than a multi-digit
increment, where the data is stored in big-endian order. So the
following (classical) algorithm would seem appropriate:
void
nextPattern( std::string& pattern )
{
static char const firstDigit = 'A';
static char const lastDigit = 'Z';
static std::string const invalidPattern( 1, '[' );
std::string::reverse_iterator current = pattern.rbegin();
std::string::reverse_iterator end = pattern.rend();
while ( current != end && *current == lastDigit ) {
*current = firstDigit;
++ current;
}
if ( current != end ) {
++ *current;
} else {
pattern = invalidPattern;
}
}
Formally, there is no guarantee in the standard that the letters will
be encoded in sequential ascending order, so for maximum portability,
you probably should in fact use an std::vector<int> with values in the
range [0, 26), and map those to letters just befor output. This
would be trivial if you put all of these operations in a class, since
the internal representation wouldn't be visible to the client code.
Something like:
class PatternGenerator
{
std::vector<int> myData;
public:
explicit PatternGenerator()
: myData( 8, 0 )
{
}
void next()
{
static int const lastDigit = 26;
std::vector<int>::reverse_iterator current = pattern.rbegin();
std::vector<int>::reverse_iterator end = pattern.rend();
while ( current != end && *current == lastDigit - 1 ) {
*current = 0;
++ current;
}
if ( current != end ) {
++ *current;
} else {
myData.front() = lastDigit;
}
}
bool isValid() const
{
return myData.front() < lastDigit;
}
friend std::ostream& operator<<(
std::ostream& dest, PatternGenerator const& obj )
{
static char const characterMap[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ( std::vector<int>::iterator current = obj.myData.current();
current != obj.myData.end():
++ current ) {
dest << characterMap[*current];
}
return dest;
}
};
(Note that things like isValid become simpler, because they can depend on the class invariants.)
Given this, all you have to write is:
int
main()
{
PatternGenerator pass;
while ( pass.isValid() ) {
std::cout << pass << std::endl;
pass.next();
}
return 0;
}
{'A','A','A','A','A','A','A','A','\0'}, and it will work. You are treating the array as a C-string when printing it. It is therefore expected to be terminated by a'\0'.