Для начала, это определенно не тот случай для вложенного цикла. По факту,
весь ваш код сводится к:
pass = initialPattern();
while ( isValidPattern( pass ) ) {
nextPattern( pass );
std::cout << pass << std::endl;
}
(Но мне интересно, если вы действительно не хотите сделать вывод до того, как
приращение.)
Теперь все, что вам нужно сделать, это определить тип прохода и соответствующий
функции; Вы могли бы даже рассмотреть
положить все в классе, так как все функции работают на
тот же экземпляр данных.
Судя по вашему коду, pass
должно быть std::string
с 8
персонажи; инициализация может быть написана:
std::string pass( 8, 'A' );
isValidPattern
, видимо, смотрит только на первый символ. (Я не
конечно, это правильно, но это то, что делает ваш код.) Что-то вроде:
bool
isValidPattern( std::string const& pattern )
{
return pattern[0] != '[';
}
согласно вашему коду, но что-то вроде:
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();
}
показалось бы более уместным. (Конечно, если вы делаете какие-либо
кодирование с текстом, у вас уже есть NotIsUpper
и его братья и сестры в
ваш набор инструментов.)
Наконец, nextPattern
кажется не более чем многозначным
инкремент, где данные хранятся в порядке с прямым порядком байтов. Итак
следующий (классический) алгоритм показался бы уместным:
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;
}
}
Формально в стандарте нет гарантии, что буквы будут
быть закодирован в последовательном порядке возрастания, поэтому для максимальной переносимости,
вам, вероятно, следует использовать std::vector<int>
со значениями в
диапазон [0, 26)
, и сопоставьте их с буквами только для вывода. это
было бы тривиально, если вы поместите все эти операции в классе, так как
внутреннее представление не будет видно клиентскому коду.
Что-то вроде:
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;
}
};
(Обратите внимание, что такие вещи, как isValid
становятся проще, потому что они могут зависеть от инвариантов класса.)
Учитывая это, все, что вам нужно написать, это:
int
main()
{
PatternGenerator pass;
while ( pass.isValid() ) {
std::cout << pass << std::endl;
pass.next();
}
return 0;
}