Я должен выровнять стек по правому краю по левому
используя вложенные для циклов, но я не могу понять, условия на
два внутренних.
Я думаю, что ваша проблема со словом может быть сделана более разрешимой, если использовать более значимые имена переменных и функций. Эти слова могут помочь вам понять, как вы думаете о своих усилиях, и, безусловно, откроют больше для ваших читателей. Символы одиночного символа не имеют большого значения.
С другой стороны, существует несколько попыток, когда отдельные имена символов и переменные более чем допустимы, но фактически ожидаемы ... например, матричная математика (возможно, для компьютерной графики) часто использует индексы, называемые просто x, y , z и, возможно, t, и не вызовет проблем у внимательного автора.
Я подготовил для вас 4 примера, которые я обозначил «X», «a», «b» и «c». Каждый пример упакован как функтор (для моего удобства).
Для начала, функторы 'X' и 'a' являются «одинаковыми», так что я ожидаю, что компилятор генерирует очень похожий код. Вы не сможете подтвердить это одним взглядом. Разница в том, что в примере 'X' есть одиночные переменные и имена функций. И пример «а» имеет более 1 буквенных символов, но не полные «правильно написанные» слова, либо.
Описание функтора:
'X' итеративный, возвращает int 0, шаблон шага
переменные: n, i, j, k
функции: x (), p ()
'a' итеративный, возвращает int 0, шаблон cout of step
переменные: maxPtrnHgtWdth, шаг
функция: exec (), dotPndLine ()
цель: Возможно, более длинные имена символов могут помочь в разработке или, по крайней мере, облегчат чтение.
class T934X_t // 'X'
{
public:
int operator()(int64_t n) { return x(n); }
private:
int x(int64_t n)
{
cout << "\n\n\n int T934X_t()(int64_t) -->"
<< " int x (int64_t) (" << n
<< ")\n iterative, return 0, cout step pattern, vars: n, i, j, k ";
for (uint i = 0; i < n; ++i) {
p(n, i+1);
}
return 0;
}
// 1..n
void p (int64_t n, uint j)
{
cout << "\n ";
for (uint k = 0; k < (n - j); ++k) { cout << '.'; }
for (uint k = 0; k < j; ++k) { cout << '#'; }
cout << ' ' << flush;
}
}; // class T934X_t
class T934a_t // 'a'
{
public:
int operator()(int64_t maxPtrnHgtWdth) { return exec(maxPtrnHgtWdth); }
private:
int exec (int64_t maxPtrnHgtWdth)
{
cout << "\n\n\n int T934a_t()(int64_t) -->"
<< " int exec (int64_t) (" << maxPtrnHgtWdth
<< ")\n iterative, return 0, cout 'step' pattern ";
for (uint step = 0; step < maxPtrnHgtWdth; ++step) {
dotPndLine (maxPtrnHgtWdth, step+1);
}
return 0; // meaningless
}
// 1..8
void dotPndLine (int64_t maxPtrnHgtWdth, uint step)
{
cout << "\n "; // 8 - 1..8
for (uint dotCt = 0; dotCt < (maxPtrnHgtWdth - step); ++dotCt) { cout << '.'; }
for (uint pndCt = 0; pndCt < step; ++pndCt) { cout << '#'; }
cout << " " << flush;
}
}; // class T934a_t
Больше описаний функторов: (еще два для рассмотрения)
'b': итеративный, возвращает строку, содержащую шаблон шага
- переменные: maxPtrnHgtWdth, шаг
- функции: exec (), dotPndLine ()
Похож на 'a', но использует stringstream вместо 'on-the-fly-cout'. Это простой вид «отложенного» метода вывода. Я использую это для поддержки совместного использования (несколькими потоками) одного выходного потока (например, cout).
'c': хвостовая рекурсия , возвращает строку, которая содержит шаблон шага
- vars: maxPtrnHgtWdth, step, dotct, pndCt
- функции: exec (), execR (), dotPndLine (), dotR (), pndR ()
Я включил, потому что я фанат рекурсии, и подумал, что эти относительно простые примеры рекурсивного зацикливания могут быть полезны для новичка в рекурсии.
class T934b_t // 'b'
{
stringstream ss;
int64_t maxPtrnHgtWdth;
public:
string operator()(int64_t a_max)
{
maxPtrnHgtWdth = a_max;
exec ();
return ss.str();
}
private:
void exec ()
{
ss << "\n\n\n string T934b_t()(int64_t) -->"
<< " void exec (int64_t) (" << maxPtrnHgtWdth
<< ")\n iterative, return string which contains step pattern";
for (int64_t step = 0; step < maxPtrnHgtWdth; ++step) // step 0..7
{
dotPndLine (step+1); // build each line with dots and pound signs
}
}
// 1..8
void dotPndLine (int64_t step)
{
ss << "\n "; // 8 - 1..8
for (int64_t dotCt = 0; dotCt < (maxPtrnHgtWdth - step); ++dotCt) { ss << '.'; } // dot
for (int64_t pndCt = 0; pndCt < step; ++pndCt) { ss << '#'; } // pnd
ss << " ";
}
}; // class T934b_t
class T934c_t // 'c'
{
stringstream ss;
int64_t maxPtrnHgtWdth;
public:
string operator()(int64_t max)
{
maxPtrnHgtWdth = max;
exec();
return ss.str();
}
private:
void exec ()
{
ss << "\n\n\n string T934c_t()(int64_t): -->"
<< " void exec (int64_t) (" << maxPtrnHgtWdth
<< ")\n tail recursive, return string which contains step pattern, ";
execR (maxPtrnHgtWdth); // entry to recursive code
}
// 8..1
void execR (int64_t step)
{
if (0 >= step) return; // recursion termination
dotPndLine (step-1); // build each line with dots and pound signs
execR (step-1); // tail recursion
}
// 7..0
void dotPndLine (int64_t step)
{
ss << "\n ";
dotR (step); // 7..0 dots
pndR (maxPtrnHgtWdth-step); // 1..8 pound sign
ss << ' ';
}
// 7..0
void dotR (int64_t dotCt) {
if (0 >= dotCt) return; // recursion termination
ss << '.';
dotR (dotCt-1); // tail recursion
}
// 1..8
void pndR (int64_t pndCt) {
if (0 >= pndCt) return; // recursion termination
ss << '#';
pndR (pndCt-1); // tail recursion
}
}; // class T934c_t
Я строю эти 4 функтора (и основной, и некоторый простой код для активации), все в одном файле.
#include <iostream>
using std::cout, std::cerr, std::endl, std::flush;
#include <string>
using std::string, std::stol;
#include <sstream>
using std::stringstream;
#include <cassert>
class T934X_t // 'X'
{
// ... move previous code here
}
class T934a_t // 'a'
{
// ... move previous code here
}
class T934b_t // 'b'
{
// ... move previous code here
}
class T934c_t // 'c'
{
// ... move previous code here
}
// main invokes the functor
class T934_t
{
public:
int operator()(int argc, char* argv[])
{
if (argc < 2) {
cerr << "\n expecting height/width limit: uint > 2\n" << endl;
return -1;
}
if(false) // enable for system info
{
string s;
s.reserve(26000000);
cout << "\n\n T934_t() (implementation details)" // ubuntu, g++7
<< "\n sizeof(long int): " << sizeof(long int) // 8 bytes
<< "\n sizeof(int64_t) : " << sizeof(int64_t) // 8 bytes
<< "\n string.size() : " << s.size() // 0 elements
<< " sizeof(string) : " << sizeof(string); // 32 bytes
for (int i=0; i<1000000; ++i)
for (char kar='a'; kar<='z'; ++kar)
s += kar;
cout << "\n string.size() : " << s.size() // 260000 elements
<< " sizeof(string) : " << sizeof(string) // 32 bytes
<< endl;
} // string s destructs here
// user selected stair step max Pattern Height Width
int64_t maxPtrnHgtWdth = stol(argv[1]);
if (maxPtrnHgtWdth < 2) { maxPtrnHgtWdth = 8; }
else if (maxPtrnHgtWdth > 80) { maxPtrnHgtWdth = 79; } // arbitrary limit
return exec (maxPtrnHgtWdth);
}
private:
// this functor exec() invokes 'X', 'a', 'b', and 'c'
int exec (int64_t maxPtrnHgtWdth)
{
int retVal = 0;
// iterative, return 0 ignored, cout step pattern,
// vars: n, i, j, k, functions x(), p()
(void)T934X_t()(maxPtrnHgtWdth);
// iterative, return 0 ignored, cout 'step' pattern,
// functions exec(), dotPndLine()
(void)T934a_t()(maxPtrnHgtWdth);
// iterative, return string which contains step pattern
cout << T934b_t()(maxPtrnHgtWdth) << flush;
// tail recursive, returns string which contains step pattern
cout << T934c_t()(maxPtrnHgtWdth) << flush;
cout << "\n\n\n T934_t::exec()"
<< " (__cplusplus: " << __cplusplus << ")"
<< std::endl;
return retVal;
}
}; // class T934_t
int main(int argc, char* argv[]) { return T934_t()(argc, argv); }