如何更好地理解嵌套循环?

问题描述 投票:2回答:2

我的问题是我不能很好地理解嵌套循环来回答这个问题。我应该使用嵌套for循环右对齐我在左对齐上创建的堆栈,但我无法弄清楚两个内部循环的条件。

正确答案:

Height = 8
.......#
......##
.....###
....####
...#####
..######
.#######
########

我的答案:

Height = 8
.......#
.......#......#
.......#......#.....#
.......#......#.....#....#
.......#......#.....#....#...#
.......#......#.....#....#...#..#
.......#......#.....#....#...#..#.#
.......#......#.....#....#...#..#.##

我玩过它,把它当回事,没什么。我做了(k = 7,k> j,k--),(k = 0,k <n-1,k ++),k <j + 7,我画了桌子,我知道高度几乎相同作为空格的值但在每一行上反转。我也知道哈希值和空格的值应该等于用户输入的高度。

它应该从用户那里获取一个值,但是我已经在一个单独的文件上进行了处理,其中值n是简化的高度,并且在没有其余程序的情况下进行处理。

#include <stdio.h>

int main(void) {
    int n = 8;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < i; j++) {
            for(int k = 7; k > j; k--) {
                printf(".");
            }
            printf("#");
        }
        printf("\n");
    }
}
c++ loops for-loop nested nested-loops
2个回答
4
投票

它实际上非常简单。写一个表格,每行,你需要打印多少空格和'#'

n == 8

| output   | line | num_spaces | num_signs |
| -------- | ---- | ---------- | --------- |
| .......# | 1    | 7          | 1         |
| ......## | 2    | 6          | 2         |
| .....### | 3    | 5          | 3         |
| ....#### | 4    | 4          | 4         |
| ...##### | 5    | 3          | 5         |
| ..###### | 6    | 2          | 6         |
| .####### | 7    | 1          | 7         |
| ######## | 8    | 0          | 8         |    

对于line,您可以从01n开始,然后向后退。选择最简单的东西。您将看到从1开始是您示例中最简单的。

现在,对于每个line,我们需要确定我们打印多少num_spacesnum_signs。他们应该依靠linen

对于num_spaces它是n - linenum_signs它是line

所以代码应如下所示:

// for each line
for (int line = 1; line <= n; ++line)
{
    // print n - line spaces

    // print line # characters

    // print \n
}

使用循环,代码将如下所示:

// for each line
for (int line = 1; line <= n; ++line)
{
    // print n - line spaces
    for (int i = 0; i < n -line; ++i)
        std::cout << ' ';

    // print line # characters
    for (int i = 0; i < line; ++i)
        std::cout << '#';

    std::cout << '\n';
}

std::cout.flush();

但实际上并不推荐这样做。你可以摆脱那些内部循环。一个好的简单方法是使用字符串:

// for each line
for (int line = 1; line <= n; ++line)
{
    // print n - line spaces
    std::cout << std::string(n - line, ' ');

    // print line # characters
    std::cout << std::string(line, '#');

    std::cout << '\n';
}

std::cout.flush();

你甚至可以更进一步:

// for each line
for (int line = 1; line <= n; ++line)
{
    // print n - line spaces and line # characters
    std::cout << std::string(n - line, ' ') << std::string(line, '#') << '\n';
}

std::cout.flush();

0
投票

我应该使用嵌套for循环右对齐我在左对齐上创建的堆栈,但我无法弄清楚两个内部循环的条件。

我认为通过使用更有意义的变量和函数名称可以使您的单词问题更容易解决。这些词语可能有助于指导您如何看待自己的努力,并且肯定会向您的读者揭示更多内容。单个字符符号几乎没有意义。

另一方面,确实存在一些努力,其中单个字符名称和变量超过容忍,但实际上是预期的...例如,矩阵数学(可能用于计算机生成的图形)通常使用简单地命名为x,y,z和也许是,并且对于细心的作者来说不会引起任何问题。


我为你准备了4个例子,我已经标注了'X','a','b'和'c'。每个示例都打包为一个仿函数(为方便起见)。

开始时,仿函数'X'和'a'是“相同的”,因此我希望编译器生成非常相似的代码。您可能无法一眼就确认。不同之处在于示例'X'具有单个字符变量和函数名称。例如'a'有超过1个字母的符号,但也没有完整的'正确拼写'字样。

Functor描述:

  1. 'X'迭代,返回int 0,步骤模式的cout vars:n,i,j,k 函数:x(),p()
  2. 'a'迭代,返回int 0,步骤模式的cout vars:maxPtrnHgtWdth,step function: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

更多Functor描述:(还有两个要考虑)

  1. 'b':iterative,返回包含步骤模式的字符串 vars:maxPtrnHgtWdth,step 函数:exec(),dotPndLine()

与'a'类似,但使用stringstream而不是'on-the-fly-cout'。这是一种简单的“延迟”输出技术。我使用它来支持单个输出流(例如cout)的共享(通过多个线程)。

  1. 'c':tail递归,返回一个包含step模式的字符串 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); }
© www.soinside.com 2019 - 2024. All rights reserved.