[英]setw() imbues wrong output on strings containing UTF-8 multi-byte characters/code points
我需要輸出一些可能是 UTF-8 多字節的數據,我需要使用setw()
保持它們的格式。
當字符是多字節序列時,對齊丟失並且setw()
無法正常工作。
//#include <stdio.h>
#include <locale>
#include <iostream>
//#include <fstream>
#include <iomanip>
//#include <sstream>
int main(int argc, char **argv)
{
std::locale l=std::locale("en_US.utf8");
std::locale::global(l);
std::cout.imbue(l);
std::cout<<std::endl;
std::cout<<std::setw(40)<<std::right<<"hi “my” friend"<<std::endl;
std::cout<<std::setw(40)<<std::right<<"hi -my- friend"<<std::endl;
return 0;
}
輸出是:
hi “my” friend
hi -my- friend
我錯過了什么?
我必須指出,字符“
和”
不是正常的"
,而是另外兩個字符,在 UTF-8 中每個字符由三個字節表示。
字符串文字"hi -my- friend"
包含 14 個字符。 字符串文字"hi “my” friend"
包含 18 個字符:符號“
和”
由 3 個字符/字節編碼。 cout
按原樣輸出這些字符,目標終端將 3 字節序列轉換為單個符號。
因此,從流的角度來看,一切都很好:它輸出(width - strlen(literal) )
填充字符,然后是strlen(literal)
字符, width
總計。 它不處理可能的多字節序列,也不知道目標終端將幾個字符轉換為一個符號。
您可以通過計算字符串在寬表示中的字符數來完成此格式設置,然后計算字符串長度和寬表示之間的差異,然后將該差異添加到傳遞給setw
,例如:
std::mbstate_t state = std::mbstate_t();
std::string s = "hi “my” friend";
const char *cp = s.c_str();
size_t len = mbsrtowcs(nullptr, &cp, s.size(), &state);
std::cout << setw(40 + (s.size() - len)) << std::right << s << std::endl;
您可以將此功能編碼為一個函數,該函數將字符串作為參數並返回要添加到 setw 調用的差值:
size_t f(const std::string &s)
{
std::mbstate_t state = std::mbstate_t();
const char *cp = s.c_str();
size_t len = mbsrtowcs(nullptr, &cp, s.size(), &state);
return s.size() - len;
}
...
std::string s = "hi “my” friend";
std::cout << std::setw(40 + f(s)) << std::right << s << std::endl;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.