C ++专栏,完美排列

时间:2016-11-28 18:31:29

标签: c++ multiple-columns

所以我试图编写这个代码,在完美的列中显示ASCII代码,但是这些列完全排成一列。我做错了什么?

#include <iostream>   // cout
#include <iomanip>    // setw

using namespace std;
int main ()
{
    int a;                                                                    
    for(a=32;a<=255;++a)
    {
        cout << a << setw(2) <<static_cast<char>(a)<< setw(20);              
    }

    return 0;
}

这就是我想要它的样子, http://www.asciitable.com/index/extend.gif

4 个答案:

答案 0 :(得分:2)

这将会有点长,所以...工作代码位于底部,之前的所有内容都是一个解释。

  1. :在同一行中包含 n 列的简单方法是在每个 n 条目后有条件地插入换行符。最简单的方法是使用模运算,将第一个条目视为1,并检查除以 n 时的余数是0

        const int NUMBER_OF_COLUMNS = 5;
    
        // ...
    
        for(a=32;a<=255;++a)
        {
            cout << /* output... */
                 << ((a - 31) % NUMBER_OF_COLUMNS == 0 ? "\n" : "");
        }
    

    这是如何工作的:我们在循环中添加或减去它,就像它从1开始一样(在这种情况下,通过减去31因为它从32开始),然后在该值上使用模数来确定它是否可以被 n 完全整除。如果是,我们插入"\n"(换行符);如果不是,我们会插入""(没有)。

    这也可以修改为始终在循环结束时输出换行符,而不会将cout << endl;cout << '\n';放在循环之外。

    // Change...
    << ((a - 31) % NUMBER_OF_COLUMNS == 0 ? "\n" : "");
    // To...
    << ((a - 31) % NUMBER_OF_COLUMNS == 0 || a == 255 ? "\n" : "");
    // Inserts "\n" every n columns, OR when a is 255.
    

    或者,您可以将检查放在输出的开头,并将循环计数器视为以0开始;在这种情况下,我们将减去32。

        const int NUMBER_OF_COLUMNS = 5;
    
        // ...
    
        for(a=32;a<=255;++a)
        {
            cout << ((a - 32) % NUMBER_OF_COLUMNS == 0 ? "\n" : "")
                 << /* output... */;
        }
    

    这将在输出的最开始处设置换行符,但如果不需要,可以通过专门检查a实际上是否为起始值来避免。 / p>

    // Change...
    ((a - 32) % NUMBER_OF_COLUMNS == 0 ? "\n" : "")
    // To...
    ((a - 32) % NUMBER_OF_COLUMNS == 0 && a != 32 ? "\n" : "")
    // Inserts "\n" every n columns, unless a is 32.
    

    如果您愿意,您还可以修改此方法,让用户指定要显示的列数。

  2. 间距:如果您传递std::setw()一个常量值,它可能会在某些地方搞乱您的格式。就目前而言,间距存在两个问题。

    for(a=32;a<=255;++a)
    {
        cout << a
             << setw(2)   // Doesn't take into account the number of digits in a.
             <<static_cast<char>(a)
             << setw(20); // Doesn't take into account character 127 not being a graphical
                          //  character.
    }
    

    作为替代方案,您可以使用\t输出标签,更改应用std::setw()的输出,或使用一点逻辑来确定要传递的值std::setw()

    1. 如果宽度是常数,第一个没有正确排列。这是因为std::setw()会影响它之后的下一个输出,并且转换为char可以保证此输出始终只是一个字符(因此,如果指定宽度 x ,它将用 x - 1个空格填充。有两种方法可以解决此问题:在输出std::setw()之前使用std::lefta ...

      cout << setw(4) << left // Tells cout to make sure a is at least 4 characters,
                              //  padding it at the end if necessary.
                              // 4 characters are used to account for 3 digits + a space.
           << a
           << /* output... */;
      

      或者将std::setw()应用于static_cast<char>(a),就像您现在一样,但是使用一点逻辑来确定值......

      cout << a
           << setw(a < 100 ? 3 : 2)           // Set width to 3 if a < 100, or 2 otherwise.
           << static_cast<char>(a)
           << /* output... */;
      

      如果我们选择第一个,那么最好将std::left移到循环之外,如下所示:

      cout << left;
      for(a=32;a<=255;++a)
      {
          cout << setw(4)
               << /* output.. */;
      }
      cout << right; // Reset to default.
      

      由于我们未在循环中传递std::rightstd::internal,因此没有理由每次都传递std::left

    2. 在某些平台上,字符127会破坏其后的所有内容的格式,直到行尾;这是因为它实际上并不是一个图形字符,因此实际上不会被显示(Unicode有&#34; DEL&#34;和Win32控制台字体有一个房子,所以他们可以显示它以图形方式)。解决此问题的最简单方法是在\t之后输出一个或多个制表位或static_cast<char>(a)

      cout << /* output... */
           << static_cast<char>(a)
           << "\t\t"
           << /* output... */;
      
  3. Wait, what's that ?: thing? :这将是conditional operator,非官方称为&#34;三元运算符&#34;。 This operator takes 3 operands, and acts like a miniature if ... else statement that can be used as an expression。它用作:

    条件 ? true-result : false-result

    条件转换为bool,可以是任何可以计算为布尔值的值。如果true,则运算符求值为 true-result ;如果false,则评估为 false-result 。这个运算符看起来有点奇怪,但非常有用,因为它允许在不能使用if语句的情况下应用条件逻辑(例如在变量赋值期间)。

    在这里,我使用了两次:

    • 要在每个 n 列之后有条件地将换行符插入std::cout。请注意,它括在括号中;这是因为it has lower precedence than the << operator。它评估为"\n"或空字符串"",具体取决于a的值。
    • 确定要传递std::setw()的值,如果它已应用于static_cast<char>(a)而不是a。如果a小于100,则评估为3,否则为2
  4. 因此,结合这些,我们得到的结果如下:

    #include <iostream>   // cout
    #include <iomanip>    // setw, left, right
    
    using namespace std;
    int main ()
    {
        const int NUMBER_OF_COLUMNS = 8; // Number of columns per line.
    
        cout << left; // Append padding after output.
        int a;
        for(a=32;a<=255;++a)
        {
            cout << setw(4)                         // Pad until 4 characters.
                 << a
                 << static_cast<char>(a)
                 << "\t\t"                          // Use tabs for spacing.
                 << ((a - 31) % NUMBER_OF_COLUMNS == 0 || a == 255 ? "\n" : "");
                   // Insert newline when specified, and after outputting the last entry.
        }
        // This isn't necessary since you exit right after, but it's a useful habit to develop
        //  if you format text for console output frequently.
        // Remove if desired.
        cout << right; // Reset to default.
    
        return 0;
    }
    

    我还建议:
    1)移动using namespace std;内部main()本身,和/或将其替换为:
        using std::cout; using std::left; using std::right; using std::setw;
    2)在a循环条件中声明forfor(int a=32;a<=255;++1)

答案 1 :(得分:0)

试试这个:

#include <iostream>   // cout
#include <iomanip>    // setw

using namespace std;
int main()
{
    int a;
    int count = 0;
    for (a = 32; a <= 255; ++a)
    {
        cout << a << setw(2) << static_cast<char>(a);
        if (count != 3)
        {
            cout << setw(20);
            count++;
        }
        else
        {
            count = 0;
            cout << endl;
        }
    }
    cout << endl;

    return 0;
}

PS:如果您希望有更多相同长度的列,请尝试将此if (count != 3)和此cout << setw(20);更改为if (count != 6)cout << setw(9);

答案 2 :(得分:-1)

我认为你正在寻找这样的东西:

#include <iostream>   // cout
#include <iomanip>    // setw

using namespace std;
int main ()
{
    int a;                                                                    
    for(a=32;a<=255;++a)
    {
        cout << setw(3) << a << setw(20) <<static_cast<char>(a) << std::endl;              
    }

    return 0;
}

setw(3)出现在角色之前,你想要3而不是2,如评论中所述。 你也忘了在最后打印换行符。

要获得类似于链接的内容,您可以执行以下操作:

#include <iostream>   // cout
#include <iomanip>    // setw

using namespace std;
int main ()
{
    int a;
    int nColumns = 14;
    for(a=32;a<=255;++a)
    {
        cout << setw(10) << a << setw(8) <<static_cast<char>(a);
        if((a-31)%nColumns == 0)
        {
            cout<<endl;    
        }
    }
    return 0;
}

我的在线编译器不会显示130到255之间的字符,因此会出现中断(130后列不排列)。如果你的每个角色都能正确显示,你就不应该看到任何中断。

Example

答案 3 :(得分:-1)

如前面评论中所述,您需要在输出值之前询问std::cout正确的宽度,并且当您有一定数量的列时,您需要有一种方法来输出新行。所以这里只是对代码的一个小编辑(这将使行中的数字增加,如果你想要在列而不是行中增加值,你需要做更多的数学运算,而不是直接输出值,将它们附加到每行的字符串中,然后在结尾处输出值。我将第一个解决方案添加到此答案的结尾,因为行增量答案已由其他人给出:-)):

#include <iostream>
#include <iomanip>

using namespace std;
int main ()
{
    int nocols = 5;    // number of columns that you want
    for (int a = 32; a < 256; ++a)
    {
        cout << setw(3) << a << setw(20) << static_cast<char>(a);
        if (!((a - 31) % nocols))
            cout << endl;
    }

    return 0;
}

以下是列增量格式:

int nocols = 8;    // number of columns that you want
int norows = 1 + (256 - 32 - 1) / nocols; // number of rows

for (int row = 0; row < norows; ++row)
{
    for (int col = 0; col < nocols; ++col)
    {
        int ch = 32 + norows * col + row;
        if (ch < 256)
            cout << setw(3) << ch << setw(10) << static_cast<char>(ch) << ' ';
    }
    cout << endl;
}