英文:
Get the width of Chinese strings correctly
问题
我想在文本“这是一个测试”周围加上边框,但我无法获得它的实际宽度。对于英文文本,它可以完美地工作。
以下是我的分析:
len
告诉我这个:
这是一个测试 18
aaaaaaaaa 10
つのだ☆HIRO 16
aaaaaaaaaa 10
runewidth.StringWidth 告诉我这个:
这是一个测试 12
aaaaaaaaa 10
つのだ☆HIRO 11
aaaaaaaaaa 10
func main() {
fmt.Println("这是一个测试 |")
fmt.Println("aaaaaaaaaa | 10*a")
fmt.Println()
fmt.Println("这是一个测试 |")
fmt.Println("aaaaaaaaa | 9*a")
fmt.Println()
fmt.Println("两者都不等于中文文本。")
fmt.Println("(竖线)行不在同一行上。")
}
问题:
如何使我的框(第一个截图)正确显示?
英文:
I want to make a border around the text 这是一个测试
, but I cannot get the actual width of it. With English text, it does work perfectly.
Here is my analysis:
len
tells me this:
这是一个测试 18
aaaaaaaaa 10
つのだ☆HIRO 16
aaaaaaaaaa 10
runewidth.StringWidth tells me this:
这是一个测试 12
aaaaaaaaa 10
つのだ☆HIRO 11
aaaaaaaaaa 10
func main() {
fmt.Println("这是一个测试 |")
fmt.Println("aaaaaaaaaa | 10*a")
fmt.Println()
fmt.Println("这是一个测试 |")
fmt.Println("aaaaaaaaa | 9*a")
fmt.Println()
fmt.Println("Both are not equal to the Chinese text.")
fmt.Println("The (pipe) lines are not under each other.")
}
Question:
How can I get my box (first screenshot) to appear correctly?
答案1
得分: 4
Unicode字符(如中文字符)在Golang中占用3个字节,而ASCII只占用1个字节。这是设计上的规定。
如果你想要检查Unicode字符的实际字符串大小,可以使用unicode/utf8内置包。
fmt.Printf("String: %s\nLength: %d\nRune Length: %d\n", c, len(c), utf8.RuneCountInString(c))
// String: 这是一个测试
// Length: 18
// Rune Length: 6
更基本的计数方法是使用for循环。
count := 0
for range "这是一个测试" {
count++
}
fmt.Printf("Count=%d\n", count)
// Count=6
关于以表格形式漂亮打印中文和英文字符串,似乎没有直接的方法。即使是tabwriter在这种情况下也不起作用。一个小的解决方法是使用csv writer,如下所示:
data := [][]string{
{"这是一个测试", "|"},
{"aaaaaaaaaa", "|"},
{"つのだ☆HIRO", "|"},
{"aaaaaaaaaa", "|"},
}
w := csv.NewWriter(os.Stdout)
defer w.Flush()
w.Comma = '\t'
for _, row := range data {
w.Write(row)
}
这样应该按预期打印数据。不幸的是,StackOverflow没有打印出与我在终端中看到的相同格式。但是Playground可以帮助我们。点击这里
注意
:这适用于字符的rune大小彼此接近的字符串。对于较长的字符串,你需要更多的解决方法。
英文:
Unicode characters (like Chinese characters) in Golang take 3 bytes, while ASCII only takes 1 byte. That's by design.
If you wish to check the actual string size of unicode character, use unicode/utf8 built-in package.
fmt.Printf("String: %s\nLength: %d\nRune Length: %d\n", c, len(c), utf8.RuneCountInString(c))
// String: 这是一个测试
// Length: 18
// Rune Length: 6
More basic way to count is by using for loop.
count := 0
for range "这是一个测试" {
count++
}
fmt.Printf("Count=%d\n", count)
// Count=6
About the pretty print of Chinese and English strings in tabular format, there seems to be no direct way. Nor the tabwriter works in this case. A small hack-around this is to use csv writer as follows:
data := [][]string{
{"这是一个测试", "|"},
{"aaaaaaaaaa", "|"},
{"つのだ☆HIRO", "|"},
{"aaaaaaaaaa", "|"},
}
w := csv.NewWriter(os.Stdout)
defer w.Flush()
w.Comma = '\t'
for _, row := range data {
w.Write(row)
}
This should print data as expected. Unfortunately, StackOverflow isn't printing the same format as I see in terminal. But Playground to our rescue. Click Here
Note
: This works for strings with rune size close enough to one another. For lengthier strings, you'd need more work-around.
答案2
得分: 0
你的问题(正如mkopriva在评论中指出的)是一个显示问题,无法通过任何计数技巧来解决。
当我们显示变宽字体或比例字体的英文文本时,与等宽字体文本相比,我们也会遇到同样的问题。比较一下:
mmmm, tasty
iiii, tasty?
与:
&nbsp;&nbsp;&nbsp;&nbsp;mmmm, tasty<br>
&nbsp;&nbsp;&nbsp;&nbsp;iiii, tasty?
(假设您使用浏览器阅读此答案!)。我们不需要打印中文字符,甚至不需要使用简单的ASCII字符就能遇到这个问题!
你需要的是一个等宽的显示字体来显示中文文本,或者可能需要一些软件以表格形式排版它,如何获得这些...又是另一个完全不同的问题。
英文:
Your problem is (as mkopriva points out in comments) a display issue, not amenable to being resolved by any sort of counting trick.
We have the same problem when we display variable-pitch, or proportional, text, vs monospace text, in English. That is, compare:
mmmm, tasty
iiii, tasty?
with:
mmmm, tasty<br>
iiii, tasty?
(assuming you use a browser to read this answer!). We don't have to print Chinese characters, or even leave simple ASCII to have the problem!
What you need is a monospaced display font for your Chinese text, or perhaps some software to typeset it in tabular form, and how you get that is ... another question entirely.
答案3
得分: 0
我认为这是你想要的翻译:
func TestChinese(t *testing.T) {
tests := []string{
"这是一个测试",
"aaaaaaaaa",
"つのだ☆HIRO",
"aaaaaaaaaa",
"这是aaaaa一个测试",
"这是一个つの测试",
}
for _, tt := range tests {
fmt.Printf("%s\t%d\t%d\n", tt, len([]rune(tt)), len([]byte(tt)))
}
}
输出:
这是一个测试 6 18
aaaaaaaaa 9 9
つのだ☆HIRO 8 16
aaaaaaaaaa 10 10
这是aaaaa一个测试 11 23
这是一个つの测试 8 24
英文:
i think this is what you want
func TestChinese(t *testing.T) {
tests := []string{
"这是一个测试",
"aaaaaaaaa",
"つのだ☆HIRO",
"aaaaaaaaaa",
"这是aaaaa一个测试",
"这是一个つの测试",
}
for _, tt := range tests {
fmt.Printf("%s\t%d\t%d\n", tt, len([]rune(tt)), len([]byte(tt)))
}
}
output:
这是一个测试 6 18
aaaaaaaaa 9 9
つのだ☆HIRO 8 16
aaaaaaaaaa 10 10
这是aaaaa一个测试 11 23
这是一个つの测试 8 24
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论