c++ 中文字符的 setw 格式化打印问题
问题引入
考虑这样的一段代码:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;void aligned_string() {string cstr1 = "中文", cstr2 = "对齐";string estr1 = "English", estr2 = "Alignment";cout << setw(20) << left << cstr1 << cstr2 << endl;cout << setw(20) << left << estr1 << estr2 << endl;
}int main() {aligned_string();
}
在默认的windows中文环境下(源代码文件和控制台的编码都是936
,即一种GBK),setw()
函数在中英文混合的场景下可以正常工作。
但是在unix环境下(默认使用UTF-8作为源代码和控制台的编码),setw()
函数在中英文混合的场景下并不能正常工作。
产生原因
setw()
函数的特性
setw()
函数中传入的参数,作为最终约定的“宽度”,并不是字符数,而是字节数。中英文在不同的编码方式下,有着不同的编码方式,每个字符所对应的字节数也不尽相同。编码方式
Windows环境下的GBK和unix环境下的UTF-8对于英文字符均使用相同的单字节的编码方式(即ASCII),而对于中文字符的编码处理并不相同:- GBK:使用定长的双字符编码。因此由于等宽字体中,中文字符的宽度是英文字符的两倍,同时字节也是两倍,所以最终得到了正常的打印效果。
- UTF-8:使用变长的字符编码。
使用以下的函数来按照小端序打印字符串"中文"
:
void print_string_bytes(string str) {for (int i = 0; i < str.size(); ++i)cout << hex << (unsigned)(unsigned char)str[i] << " ";cout << endl;
}
Windows平台的输出如下:
与在线平台的转换结果相同
Unix平台的输出如下:
和使用在线平台进行UTF-8转换的结果相同
解决方法
根据上面的分析可以得出结论:unix平台下setw()
对于中文字符处理的问题在于变长字符编码。因此只要将字符串转换为定长字符编码(比如说GBK),之后计算两者之间的差值修改setw()
的参数即可。
使用以下函数计算两种编码方式之间字节数量的差值:
#include <codecvt>
#include <locale>class chs_codecvt : public std::codecvt_byname<wchar_t, char, std::mbstate_t> {public:chs_codecvt() : codecvt_byname("zh_CN.GBK") {}
};int encoding_diff(string str) {wstring_convert<codecvt_utf8<wchar_t>> cv1;wstring wstr = cv1.from_bytes(str);wstring_convert<chs_codecvt> cv2;return str.size() - cv2.to_bytes(wstr).size();
}
其中codecvt_byname
的构造函数是protected
的,因此需要自定义一个转换器类,继承codecvt_byname
。
需要说明的是,在Linux环境下需要进行locale-gen
,编辑/etc/locale.gen
,删除zh_CN.GBK
前面的注释符号,并执行locale-gen
命令。
最终将打印函数修改如下:
void aligned_string() {string cstr1 = "中文", cstr2 = "对齐";string estr1 = "English", estr2 = "Alignment";string cestr1 = "中文English", cestr2 = "对齐Alignment";cout << setw(20 + encoding_diff(cstr1)) << left << cstr1 << cstr2 << endl;cout << setw(20 + encoding_diff(estr1)) << left << estr1 << estr2 << endl;cout << setw(20 + encoding_diff(cestr1)) << left << cestr1 << cestr2 << endl;
}
打印效果如下:
c++ 中文字符的 setw 格式化打印问题相关推荐
- c语言打印字符的函数参数,C语言格式化打印函数vsnprintf()的实现
Linux内核的格式化打印函数是printk(),它与printf()函数是类似的,都是根据格式字符串把可变参数列表转化成字符序列,然后输出到控制台. printf()是打印到标准输出stdout. ...
- php调试代码时var_dump( )打印中文字符时出现乱码解决方案
php调试代码时var_dump( )打印中文字符时出现乱码解决方案 参考文章: (1)php调试代码时var_dump( )打印中文字符时出现乱码解决方案 (2)https://www.cnblog ...
- 打印出所有的中文字符
2019独角兽企业重金招聘Python工程师标准>>> 尝试打出所有的中文字符,中文字符的16进制范围是[u4e00-u9fa5]. public static String toS ...
- c++ 把数字和中文字符分开_C语言中的字符常量与变量
字符常量与变量 在这一节中,我们来讨论字符与字符串. 1. 字符常量 如果我想在屏幕上打印"HelloWorld".应该怎样做呢?大家应该很熟悉这个代码了. #includ ...
- java中文字符怎么保证出现正确_JAVA中文字符编码问题详解
JAVA中文字符编码问题详解 JAVA的中文字符乱码问题一直很让人头疼.特别是在WEB应用中.网上的分析文章和解决方案都很多,但总是针对某些特定情况的.很多次遇到乱码问题后,经过极为辛苦的调试和搜索资 ...
- C语言中的格式化打印printf/sprintf以及嵌入式printf重定向进行DEBUG
一.printf描述 在C语言中,打印函数主要包括printf/sprintf/fprintf/snprintf等等,目的是将"给定的内容"按照"指定的格式"输 ...
- (best!)JAVA中文字符编码问题详解
转载自:http://blog.csdn.net/youyue/article/details/4580402 JAVA中文字符编码问题详解 JAVA的中文字符乱码问题一直很让人头疼.特别是在WEB应 ...
- c语言中文网_在C语言中使用中文字符
大部分C语言教材对中文字符的处理讳莫如深,甚至只字不提,导致很多初学者认为C语言只能处理英文,而不支持中文.其实C语言是一门全球化的编程语言,它支持世界上任何一个国家的语言文化,包括中文.日语.韩语等 ...
- python对浮点类型的数据进行格式化_(自用)Python Log2 数据类型、字符编码、格式化...
数据类型 1.整数 十六进制可以使用0x+数字0-9(字母a-f). 2.浮点数 一般使用科学计数法,用e代替10,比如1.2e5,为1.2×10^5. 3.字符串 可以使用单引号' ',或者双引号& ...
- python 字符编码、格式化
数据类型-布尔值 一个布尔值只有True.False两种值,要么是True,要么是False 布尔值可以用and.or和not运算 空值是Python里一个特殊的值,用None表示 Python对 ...
最新文章
- 从0到1,苏宁API网关的演进之路
- MySQL事务的特性
- Pycharm连接远程服务器进行代码调试开发
- spring boot整合mybatis步骤
- CentOS 7.6 安装 Maven 3.6.3
- Istio 网关中的 Gateway 和 VirtualService 配置深度解析
- 学习xss的一些记录(一)
- OAuth2.0_授权服务配置_授权码模式_Spring Security OAuth2.0认证授权---springcloud工作笔记144
- 亚马逊被爆内部员工卖数据改差评,中国区尤为严重!
- java实现rabbitmq任务模型(work queues), 生产者 消费者 消息队列 能者多劳
- 二元函数可导与可微的关系_视频教学:期末试卷解析之多元函数基本概念及相互关系讨论...
- Ubuntu18.04 如何解决编译objective-c出现undefined reference to objc_get_class
- d盘不见了 计算机打不开,D盘不见了怎么找回 电脑D盘没了解决方法
- 自适应YouTube视频嵌入
- cass坡度土方计算案例_四面放坡且坡度不同的工程土方,CASS怎么算?
- 不把鸡蛋放在一个篮子里面
- 语音识别(ASR)论文优选:关注语音识别系统Fairness问题Towards Measuring Fairness in Speech Recognition
- 好记性不如烂笔头The palest ink is better than the best memory
- Proxyee-down 3.x的下载与安装
- 工程流体力学笔记暂记16(欧拉积分和伯努利积分)