您的位置:首页 > 其它

学习笔记:sprintf做编码转换

2016-04-25 18:21 567 查看
#include "stdafx.h"

#include <clocale>

#include <errno.h>
#include <string.h>

void test_1(){

std::setlocale(LC_ALL,"C");

char buff[512]={0};

//sprintf函数的%s参数,是小s,意思是接收小char的字符串
//对于任意字符,原封不动的拷贝到目标缓冲区去。
//这意味着它不具有做字符编码的转换的功能。locale设置对它毫无影响。
char str[]={0x5F,0x20,'|',0xD5,0xC5,0x00};
sprintf(buff,"%s",str);
if (errno){
perror("failed reason:");
errno=0;
}

//当sprintf函数是%S参数时,是大S,意味着接收大号的char字符串(wchar_t字符串)
//对于wchar_t字符,必须是unicode编码,否则会出错。
//本例中,混入了一个GBK编码0xD5C5, 如果它在unicode范围内,很可能会造成函数失败。
wchar_t StrErr[]={0x5F20, L'|', 0xD5C5, 0x0000};
sprintf(buff,"%S",StrErr);
if (errno){
perror("failed reason:");
errno=0;
}

//为了排除错误,只保留unicode编码"张"(u5F20)
//但是仍旧函数出错误,原因是需要设置从unicode转ansi的一个重要参数:本地的语言
wchar_t StrOK[]={0x5F20, L'|', 0x0000};
sprintf(buff,"%S",StrOK);
if (errno){
perror("failed reason:");
errno=0;
}

//设置好本地的CTYPE,一般是中文GBK。除非控制面板->区域设置不是中国(简体,大陆)
std::setlocale(LC_CTYPE,"");
sprintf(buff,"%S",StrOK);  //一般会成功的。
if (errno){
perror("failed reason:");
errno=0;
}
}

#include <windows.h>
void test_2(){

//因为知道宽字节类的函数可能依赖现场,先设置成chs现场
//然后继续做测试
std::setlocale(LC_ALL,"");

wchar_t wbuff[512]={0};

//..W函数,如果是小s,将理解str为wchar数组的首地址。
//实际上str数组被理解成: wchar_t数组[0x205F,0xD57C, 0x00C5]
//这个数组没有字符串结束符,将会造成严重后果。
char str[]={0x5F,0x20,'|',0xD5,0xC5,0x00};
wsprintfW( wbuff, L"%s", str );
if (errno){
perror("failed reason:");
errno=0;
}

//大S,匹配char数组是正确的。
//但是要求str里面必须是ansi本地编码。本函数可以将ansi本地编码转为unicode
//由于{0x5F,0x20}组合序列不是GBK编码,所以函数认为是'_'和' '。
wsprintfW( wbuff, L"%S", str );
if (errno){
perror("failed reason:");
errno=0;
}

//小s接收wchar_t数组,将数组原封不动拷贝到目标中
wchar_t Str[]={0x5F20, L'|',0xD5C5 ,0x0000};
wsprintfW( wbuff, L"%s", Str );
if (errno){
perror("failed reason:");
errno=0;
}

//大S接收char数组,所以把Str认为是如下数组:
//char[ 0x20, 0x5F, 0x7C, 0x00, 0xC5, 0xD5, 0x00, 0x00 ]
//字符串的头三个字符都是ascii字符,在第4个字符截止。
//没有一对组合是GBK编码
wsprintfW( wbuff, L"%S", Str );
if (errno){
perror("failed reason:");
errno=0;
}

//用wsprintfW函数时,%S 对应 char[]    , %s 对应 wchar_t[]
//用wsprintfA函数时,%S 对应 wchar_t[] , %s 对应 char[]
//windows下,根据宏定义是否是unicode,封装了上述两个函数
//wsprintf()或者是wsprintfW,或者是wsprintfA。

TCHAR buff[512];  //宏定义封装的
TCHAR* str2=_T("张"); //宏定义封装的
wsprintf(buff, _T("%s"), str2 ); //不管是A还是W,小s,总能对应正确
if (errno){
perror("failed reason:");
errno=0;
}

wsprintf(buff, _T("%S"), str2 ); //但是S,总是对应错误的参数。所以微软提供的wsprintf宏不是很合理
if (errno){
perror("failed reason:");
errno=0;
}
}

#include <wchar.h>
void test_3(){

wchar_t buffer [100];
int cx;

std::setlocale(LC_ALL,"");

char *str = "张";
cx = swprintf ( buffer, 100, L"%S", str );
if (errno){
perror("failed reason:");
errno=0;
}

wchar_t *Str = L"张";
cx = swprintf ( buffer, 100, L"%s", Str );
if (errno){
perror("failed reason:");
errno=0;
}

//实际上,标准C函数
// sprintf         %s 对应 char ,    %S 对应 wchar_t
// swprintf        %s 对应 wchar_t,   %S 对应 char
}

int main()
{

test_3();

system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: