学习笔记:sprintf做编码转换

#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;
} 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值