2016-03-06 32 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_ *'类,它们在编码之间进行转换。您需要将数据转换为固定宽度编码,然后将其传递到标准库设施。简而言之:你正在喂它无法处理的数据。可以将数据转换为固定宽度,也可以不依赖于除原始字符输出外的其他任何内容 –