同样,使用的是VS FOR LINUX进行测试。

converting to execution character set: Invalid or incomplete multibyte or wide character

如果编译时候遇到该错误,则可以加上​​-finput-charset​​​  ​​-fexecute-charset​​  g++编译选项解决。因为linux下gcc希望源文件是UTF-8格式,所以都改成UTF-8就好了。同时,也可以vs下装个forceUTF8插件。

搜了下,网上有说使用wprintf的,比如:

wchar_t c= L'中国';
wprintf(L"%c",c);

wprintf(L"%ls\n", L"中华人民共和国");

测试的时候发现wprintf没有打印任何东西。

有说使用locale loc("chs");的:

locale loc("chs");

wcout.imbue( loc );

也有说setlocale( LC_CTYPE,"chs");的

使用chs编码,运行时就报异常了,难道都没测过么???

最后还是自己逐个调试解决了。如下:

setlocale(LC_ALL, "zh_CN.UTF-8");

wchar_t zh_cn = L'国';
wchar_t zh_cns[] = L"中国";

wchar_t another_w[sizeof(zh_cns)/sizeof(wchar_t)] = {0};
wcscpy(another_w, zh_cns);

printf("%ls。。。....%ls。。。%lc\n", zh_cns, another_w,zh_cn);

加上​​-finput-charset​​​  ​​-fexecute-charset​​  g++编译选项或者在VS中把文件设置为UTF-8带签名格式即可。

输出:

中国。。。....中国。。。国

最后,宽字符的操作函数和char不同

上述设置后,环境中就是指定的字符集了,但是vs监视窗口仍然会是显示16进制,如下:

c/c++ linux下输出中文(宽字符)_.net

将​​C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Packages\Debugger\Visualizers\stl.natvis的​​将文件583-586行改为如下:

<DisplayString Condition="_Mypair._Myval2._Myres < _Mypair._Myval2._BUF_SIZE">{_Mypair._Myval2._Bx._Buf,s8}</DisplayString>
<DisplayString Condition="_Mypair._Myval2._Myres >= _Mypair._Myval2._BUF_SIZE">{_Mypair._Myval2._Bx._Ptr,s8}</DisplayString>
<StringView Condition="_Mypair._Myval2._Myres < _Mypair._Myval2._BUF_SIZE">_Mypair._Myval2._Bx._Buf,s8</StringView>
<StringView Condition="_Mypair._Myval2._Myres >= _Mypair._Myval2._BUF_SIZE">_Mypair._Myval2._Bx._Ptr,s8</StringView>

之后,vs2015即可在debug时正常显示utf-8字符。TODO

还有个帖子说,“只需要将要显示的字符串拉到Watch中,并在变量后面添加,s8即可显示”,经测,这么做是不行的,监视窗口会报错,如下:

c/c++ linux下输出中文(宽字符)_.net_02

 

c/c++ 语言默认什么编码

  C语言是没有编码的。它的编码就是平台的默认编码。
  比方说在windows 上汉字编码用​​​gb​​​2312 或者 说cp936(​​GB​​​K一般的windows默认代码页,windows分为不同的代码页,可以查看一下​​MSDN​​​)。
​​​http://msdn.microsoft.com/zh-cn/goglobal/cc305153​​​(en-us).aspx

  C里char 就是一个字节。你定义一个汉字,比方说 char *p=“中”C语言用两个字节来存储;
  p指向的两个字节存储的就是‘中’的​​​gb​​​编码。分别是‘xd6xd0’。
  当然如果用printf("%s",p) 输入到屏幕的话,它会自动解码输出‘中’这个字。
  如果在linux平台下,它一般是uft-8编码的,汉字三个字节,道理一样。

  =========

 

 

  当C语言程序初始化时(刚进入到 main() 时),locale 被初始化为默认的 C locale,其采用的字符编码是所有本地 ANSI 字符集编码的公共部分,是用来书写C语言源程序的最小字符集(所以才起locale名叫:C)。
  也就是说,默认locale是C,字符集是ascii。
  当我们的输入是一组带有中文或者其他字符的字符串时候,他就会截断。只会转化前面的ascii字符。
  所以在中文路径下是不能work的。
  如果我们存在中文路径,或者字符,想使用wcstombs该函数来将宽字符串转为多字节字符串,那么我们就得设置系统的当前环境的locale. 

这里列出使用数组存储 1 个汉字的实例
char a[] = "字";    // 定义一个汉字的数组
char a[] = {"字"}; // 也可以加上 { }
这两种情况系统都会在后面自动加上'\0',即 a[3] = '\0' 汉字占3个字节 a[0]、a[1]和a[2];
也可以这样:
char a[4] = "字";
char a[4] = {"字"};
以上两种方法定义的空间是一样大的,都是4个字节。

char i;
for(i=0;i<4;i++)
{
printf("a[%d] = 0x%x;\r\n",i,a[i]);
}
使用char时output:
a[0] = 0xffffffe5;
a[1] = 0xffffffad;
a[2] = 0xffffff97;
a[3] = 0x00;
使用unsigned char时output:
a[0] = 0xe5;
a[1] = 0xad;
a[2] = 0x97;
a[3] = 0x00;

========最后一个完整的示例

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
using namespace std;

class Object
{

};
class Person : public Object
{
public:
char ext[32] = {0};
wchar_t* cn_name = NULL;
void Print()
{
// convert char to wchar_t, then print https://cplusplus.com/reference/cstdlib/mbstowcs/
char* pmb = (char*)malloc(32);
const wchar_t* pwc = L"Hi中国\0";
wcstombs(pmb, pwc, 31);
cout << "name:" << _name << endl;
cout << "age:" << _age << endl;
printf("ext=%s, ext_size=%d, cn_name=%ls\n", ext == NULL ? "" : ext,strlen(ext), cn_name == NULL ? L"" : cn_name); // ok, 即使有宽字符,printf也已足够
printf("pmb=%s\n", pmb); // ok
wprintf(L"cn_name=%ls,pwc=%ls,pmb=%s \n", cn_name, pwc, pmb); // ok, 任何时候在一个文件描述符上,printf/wprintf只能生效一个,另一个会忽略。谁先出现谁生效
// 宽字符依赖于locale明确设置,char数组中文不依赖
}
protected:
string _name = "peter张"; // 姓名
int _age = 18; // 年龄
};
// Student继承了Person,Student中就拥有了Person的成员
//Person叫父类/基类
//Student叫子类/派生类
class Student : public Person
{
protected:
int _stuid; // 学号
}
;
class Teacher : public Person
{
protected:
int _jobid; // 工号
};
int main(int argc, char* argv[])
{
// char* loc = setlocale(LC_ALL, "zh_CN.UTF-8");
// printf("loc=%s\n", loc);
Student s;
Teacher t;
Object p1 = t;
// t.ext = (char *)malloc(33);
// memset((void *)t.ext, 0, 33);
strcpy(t.ext, "中国ext name");

t.cn_name = (wchar_t *)malloc(32);
memset((void *)t.cn_name, 0, 32);
mbstowcs(t.cn_name, "中文扩展名balaba", sizeof("中文扩展名balaba"));

t.Print();
s.Print();
printf("from c stdio.h\n");
return 0;
}

 

 

参考


​http://www.cplusplus.com/reference/cstdio/printf/(关键时候看官方手册)​