C++列,完美排列

C++ columns, line up perfectly

本文关键字:排列 完美 C++      更新时间:2023-10-16

所以我正在尝试编写这段代码,以完美的列显示 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

这会有点长,所以...工作代码在底部,它之前的所有内容都是解释。

  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实际上不是其起始值来避免。

    // 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 个空格)。 有两种方法可以解决这个问题:在输出a之前使用std::setw()std::left...

      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 有"DEL",而 Win32 控制台字体有一个房子,所以它们可以以图形方式显示它)。 解决此问题的最简单方法是在static_cast<char>(a)之后输出一个或多个制表位或t秒。

      cout << /* output... */
      << static_cast<char>(a)
      << "tt"
      << /* output... */;
      
  3. 等等,那?:是什么?:这将是条件运算符,非正式地称为"三元运算符"。 此运算符接受 3 个操作数,其作用类似于可用作表达式的微型if ... else语句。 它用作:

    条件?真结果:假结果

    条件被转换为bool,并且可以是任何可以计算为布尔值的东西。 如果true,则运算符计算结果为真;如果false,则计算结果为假结果。 这个运算符看起来有点奇怪,但非常有用,因为它允许在无法使用if语句的情况下应用条件逻辑(例如在变量赋值期间)。

    在这里,我使用了两次:

    • 要有条件地在每n列之后插入一个换行符到std::cout中。 请注意,它括在括号中;这是因为它的优先级低于<<运算符。 它的计算结果为"n"或空字符串"",具体取决于a的值。
    • 要确定要传递的值std::setw(),如果它应用于static_cast<char>(a)而不是a。 如果a小于 100,则计算结果为 3,否则2计算结果。

因此,结合这些,我们得到的最终结果如下所示:

#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)
<< "tt"                          // 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)在for循环的条件内声明a,如for(int a=32;a<=255;++1)

试试这个:

#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);

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

#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 之后不对齐)。如果您的字符可以正确显示每个字符,则不应看到任何中断。

如前所述,在输出值之前,您需要向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;
}