我在用println!若要使用以下方法对列进行排列:
fn main() {
let name_col_w = 24;
let col_w = 9;
println!("{:<0name_col_w$}{:<0col_w$}",
"COL A",
"COL B",
name_col_w=name_col_w,
col_w=col_w,
);
println!("{:<0name_col_w$}{:<0col_w$}",
"000",
"OOO",
name_col_w=name_col_w,
col_w=col_w,
);
println!("{:<0name_col_w$}{:<0col_w$}",
"麒麟24",
"OOO",
name_col_w=name_col_w,
col_w=col_w,
);
}这一产出如下:
COL A COL B
000 OOO
麒麟24 OOO 注意,unicode字符正在超出列的界限(第二列不是全部对齐)。但是,字符串的长度小于限制(24)。
extern crate unicode_width;
use unicode_width::UnicodeWidthStr;
println!("{}","麒麟24".len()); // 8
println!("{}","麒麟24".chars().count()); // 4
println!("{}", UnicodeWidthStr::width("麒麟24")); // 6看起来,Rust格式语法实现测量的宽度错误,因为字符串应该能够适应分配的24宽度。
是否有办法使生锈识别正确的字符串宽度和正确的格式?还是我只是做了些根本错误的事?
(工作示例这里)
我正在使用来自锈病病案的字符串格式语法。
发布于 2021-01-21 07:00:45
从技术上讲,这里没有不正确的字符串长度。
问题是,大多数单空间字体根本不处理CJK,要么不支持CJK(因此退回到其他方面,这是最有可能的),要么不对CJK进行单步处理:单空间字体的全部要点是:
所有字母和字符占用相同的水平空间。
但是这里显然不是这样的,因为您自己的对齐清楚地显示了麒麟占用比3个ascii字符更多的水平空间:
"麒麟",
"OOO",因此,虽然麒麟24是4个字符,但它占用了略多于5个的视觉空间,因此填充到24个字符时抛出了对齐。
我认为除了使用足够完整的单空间字体,在您所期望的整个字符范围内使用单空间字体,或者使用GUI工具包(不会受到此问题的影响)之外,没有任何解决方案。我不确定即使是TUI/原始终端输出也能解决这个问题。
事实上,这甚至可能是GUI中的一个问题,因为如果你真的想把一切都做好,你需要通过整个渲染管道,然后测量实际的“位图”大小(实际显示在屏幕上的是什么)。
在POSIX2001中,wcwidth(3)和wcswidth(3)应该帮助查询终端,以了解字符或字符串的宽度,这可能会或不可能工作,这取决于终端,并且只有一些在实际终端中工作的概率(例如,在我的实际终端中,麒麟恰好有4个单元格,显然使用的字体集并不是这样使用的)。
您可能遇到的另一个问题是count和字符串填充工作中的代码点,由于例如组合代码点,这已经是非常不正确的,即使使用在美国英语中可能遇到的表单也是微不足道的:
println!("[{:<4}]", "é");
println!("[{:<4}]", "e\u{0301}");输出
[é ]
[é ]因为第二行使用两个代码点来处理一个单一的字素簇,这使得对齐的计算变得简单(除了前两个代码点转换为一个单一的字素簇外,它增加了2个空间编码点以达到4个,因此我们以3个字素簇而不是我们所期望的4个为结尾)。
https://stackoverflow.com/questions/65821654
复制相似问题