2016-03-06 26 views
1

我需要輸出一些可能是utf8多字節的數據,我需要使用setw保持它們的格式。 當字符是多字節序列時,alignement丟失,wset無法正常工作。setw imbue錯誤的輸出

//#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 

我缺少什麼?

我必須指出,字符「和」不正常「,而是兩個人在UTF8由三個字節表示

+0

你一直說'wset',但這不是一個函數,它不是你正在使用的函數--Setw'。 – antiduh

+0

不幸的是,注入UTF-8語言環境不會使格式化函數使用UTF-8。完成任務的最簡單方法是將所有內容轉換爲wchar_t並使用寬字符流。 –

回答

1

字符串文字"hi -my- friend"包含14個字符的字符串字面"hi 「my」 friend"包含18個字符。: 。symbols and are encoded by 3 characters/bytescout輸出這些字符原樣,它是3字節序列轉換成單個符號目標終端

所以,從圖一切的流點是好的:它輸出(width - strlen(literal))填充字符,然後strlen(literal)字符,width總,它不處理寶可能的多字節序列,並不知道目標終端將幾個字符轉換爲一個符號。

+0

預計具有區域知識的流將處理必要的轉換。如果不是這樣,那麼「setw」就沒有用處,因爲它不會做用戶期望的操作。 「imbue」的含義是什麼?顯然,需求不僅僅針對終端,而是針對文件以及這些文件可能包含utf8文本(或者選擇任何連接)。 –

+0

@GeorgeKourtis如果你仔細查看'locale'類,你會發現它幾乎沒有處理多字節編碼的問題。整個本地化庫和所有標準流需要固定寬度的編碼。它只提供了'wstring_convert'和'codecvt_ *'類,它們在編碼之間進行轉換。您需要將數據轉換爲固定寬度編碼,然後將其傳遞到標準庫設施。簡而言之:你正在餵它無法處理的數據。可以將數據轉換爲固定寬度,也可以不依賴於除原始字符輸出外的其他任何內容 –