C++ setw() 没有按预期工作
C++ setw() not working as expected
我需要在控制台上打印一些数据。我的代码是:
cout << setw(5) << left << "id" << " | " << setw(10) << left << "computer" << " | " << setw(11) << left << "subsystem" << " | " <<
setw(8) << left << "number" << " | " << setw(80) << left << "name" << " | " << setw(13) << left << "config_file" << endl;
for (int i = 0; i < rows; i++)
{
cout << setw(5) << left << subsystem_table_data[i].id << " | " << setw(10) << left << subsystem_table_data[i].computer << " | " <<
setw(11) << left << subsystem_table_data[i].subsystem << " | " << setw(8) << left << subsystem_table_data[i].number << " | " <<
setw(80) << left << subsystem_table_data[i].name << " | " << setw(13) << left << subsystem_table_data[i].config_file << endl;
}
输出(向右滚动查看):
id | computer | subsystem | number | name | config_file
1 | 1 | 2 | 0 | Computer 1 - Общая компьютерная платформа - 1 | 1
2 | 1 | 1 | 0 | Computer 1 - Launcher - 1 | 2
3 | 1 | 23 | 0 | Computer 1 - Дисплей - 1 | 3
4 | 1 | 11 | 0 | Computer 1 - Контроллер цифровой - 1 | 4
5 | 1 | 21 | 0 | Computer 1 - Отладки - 1 | 5
6 | 2 | 2 | 0 | Computer 2 - Общая компьютерная платформа - 1 | 6
7 | 2 | 1 | 0 | Computer 2 - Launcher - 1 | 7
8 | 2 | 23 | 0 | Computer 2 - Дисплей - 1 | 8
预期输出(又在右边):
id | computer | subsystem | number | name | config_file
1 | 1 | 2 | 0 | Computer 1 - Общая компьютерная платформа - 1 | 1
2 | 1 | 1 | 0 | Computer 1 - Launcher - 1 | 2
3 | 1 | 23 | 0 | Computer 1 - Дисплей - 1 | 3
4 | 1 | 11 | 0 | Computer 1 - Контроллер цифровой - 1 | 4
5 | 1 | 21 | 0 | Computer 1 - Отладки - 1 | 5
6 | 2 | 2 | 0 | Computer 2 - Общая компьютерная платформа - 1 | 6
7 | 2 | 1 | 0 | Computer 2 - Launcher - 1 | 7
8 | 2 | 23 | 0 | Computer 2 - Дисплей - 1 | 8
我建议 setw(80) << left << subsystem_table_data[i].name
代码部分有问题,但似乎找不到问题所在。据我所知,这不是因为控制台的总宽度,因为第一行打印得很好。
setw()
按设计工作。它将输出填充到给定的 字节数 1.
问题是你不需要字节数,你需要文本宽度,但除非你的文本是纯 ASCII 并使用单space 字体打印,否则这两者是不同的。
差异出现在几个层面:
- ASCII 范围以上的 Unicode 代码点被编码为多个字节(假设为 UTF-8;从各行占用的字节数来看,输出似乎是 UTF-8)。
- 多个代码点可以组合成一个字形。如果您使用的是组合范式,这是除 MacOS 文件系统之外的标准,所有西里尔字符形都是单个代码点,但在分解形式中,'й' 将是两个。
- 字形可能采用不同的屏幕宽度。
第一点是导致您错位的原因,如果您的输入中可能出现分解的字符,则可能与第二点相结合。只要你使用 monospace 字体输出,第三个不是西里尔字母的问题,但如果有任何机会你可能 运行 跨越一些 Chinese/Japanese/Korean 文本,请记住他们字形主要是 "full-width",而那些在大多数终端上采用 space 两个拉丁字母或西里尔字母。
C++ 标准库不支持字形计数。您将需要使用 unicode 支持库(例如 ICU)并自行处理对齐方式——或者采用简单的方法将文本列放在最后,这样结束就没有关系了。
1 operator<<(std::ostream&, std::string const&) 的文档根据 std::string::size()
描述了 width()
的效果,这绝对是字节数。
我需要在控制台上打印一些数据。我的代码是:
cout << setw(5) << left << "id" << " | " << setw(10) << left << "computer" << " | " << setw(11) << left << "subsystem" << " | " <<
setw(8) << left << "number" << " | " << setw(80) << left << "name" << " | " << setw(13) << left << "config_file" << endl;
for (int i = 0; i < rows; i++)
{
cout << setw(5) << left << subsystem_table_data[i].id << " | " << setw(10) << left << subsystem_table_data[i].computer << " | " <<
setw(11) << left << subsystem_table_data[i].subsystem << " | " << setw(8) << left << subsystem_table_data[i].number << " | " <<
setw(80) << left << subsystem_table_data[i].name << " | " << setw(13) << left << subsystem_table_data[i].config_file << endl;
}
输出(向右滚动查看):
id | computer | subsystem | number | name | config_file
1 | 1 | 2 | 0 | Computer 1 - Общая компьютерная платформа - 1 | 1
2 | 1 | 1 | 0 | Computer 1 - Launcher - 1 | 2
3 | 1 | 23 | 0 | Computer 1 - Дисплей - 1 | 3
4 | 1 | 11 | 0 | Computer 1 - Контроллер цифровой - 1 | 4
5 | 1 | 21 | 0 | Computer 1 - Отладки - 1 | 5
6 | 2 | 2 | 0 | Computer 2 - Общая компьютерная платформа - 1 | 6
7 | 2 | 1 | 0 | Computer 2 - Launcher - 1 | 7
8 | 2 | 23 | 0 | Computer 2 - Дисплей - 1 | 8
预期输出(又在右边):
id | computer | subsystem | number | name | config_file
1 | 1 | 2 | 0 | Computer 1 - Общая компьютерная платформа - 1 | 1
2 | 1 | 1 | 0 | Computer 1 - Launcher - 1 | 2
3 | 1 | 23 | 0 | Computer 1 - Дисплей - 1 | 3
4 | 1 | 11 | 0 | Computer 1 - Контроллер цифровой - 1 | 4
5 | 1 | 21 | 0 | Computer 1 - Отладки - 1 | 5
6 | 2 | 2 | 0 | Computer 2 - Общая компьютерная платформа - 1 | 6
7 | 2 | 1 | 0 | Computer 2 - Launcher - 1 | 7
8 | 2 | 23 | 0 | Computer 2 - Дисплей - 1 | 8
我建议 setw(80) << left << subsystem_table_data[i].name
代码部分有问题,但似乎找不到问题所在。据我所知,这不是因为控制台的总宽度,因为第一行打印得很好。
setw()
按设计工作。它将输出填充到给定的 字节数 1.
问题是你不需要字节数,你需要文本宽度,但除非你的文本是纯 ASCII 并使用单space 字体打印,否则这两者是不同的。
差异出现在几个层面:
- ASCII 范围以上的 Unicode 代码点被编码为多个字节(假设为 UTF-8;从各行占用的字节数来看,输出似乎是 UTF-8)。
- 多个代码点可以组合成一个字形。如果您使用的是组合范式,这是除 MacOS 文件系统之外的标准,所有西里尔字符形都是单个代码点,但在分解形式中,'й' 将是两个。
- 字形可能采用不同的屏幕宽度。
第一点是导致您错位的原因,如果您的输入中可能出现分解的字符,则可能与第二点相结合。只要你使用 monospace 字体输出,第三个不是西里尔字母的问题,但如果有任何机会你可能 运行 跨越一些 Chinese/Japanese/Korean 文本,请记住他们字形主要是 "full-width",而那些在大多数终端上采用 space 两个拉丁字母或西里尔字母。
C++ 标准库不支持字形计数。您将需要使用 unicode 支持库(例如 ICU)并自行处理对齐方式——或者采用简单的方法将文本列放在最后,这样结束就没有关系了。
1 operator<<(std::ostream&, std::string const&) 的文档根据 std::string::size()
描述了 width()
的效果,这绝对是字节数。