0x01 ANSI 和宽字符定义

	// ANSI 字符定义
	CHAR varChar_1 = \'a\';					// #typedef char CHAR
	CHAR varChar_2[] = "ABCDEFG";
	CHAR varChar_3[20] = "ABCDEFG";

	// 宽字符定义
	WCHAR varWChar_1 = L\'a\';				// #typedef wchar_t WCHAR
	WCHAR varWChar_2[] = L"ABCDEFG";
	WCHAR varWChar_3[20] = L"ABCDEFG";

0x02 字符串处理函数

  • 不安全的字符串处理函数
	CHAR buffer[10] = { 0 };                    // 初始化字符串
	CHAR overflow[] = "AAAAAAAAAAAAAAAAAAAA";	// 造成溢出的数据	
	int BufferSize = 20;						// 控制溢出的整数

	memset(buffer, 0x41, BufferSize);		// BufferSize 过大导致栈溢出	
	strcpy(buffer, overflow);				// overflow 过大导致栈溢出
	strcat(buffer, overflow);				// overflow + buffer 的长度过大导致栈溢出
  • 安全的字符串处理函数
	CHAR buffer[10] = { 0 };        // 初始化字符串
	CHAR overflow[] = "AAAAAAAAAAAAAAAAAAAAAA";		// 造成溢出的数据	

	errno_t res = NULL;
	// strcpy_s
	res = strcpy_s(buffer, overflow);		// 只有两个参数,那么会自动检测 overflow 的大小是否超过 buffer
	res = strcpy_s(buffer, 5, overflow);	// 限制复制的大小为 5 个字节
	// strcat_s
	res = strcat_s(buffer, overflow);		// 由于 overflow 大于 buffer,所以引发异常

异常如下
在这里插入图片描述

0x03 其他安全的字符串处理函数

	WCHAR Buffer[10] = L"AAAAAA";
	WCHAR LinkBuffer[] = L"A";
	STRSAFE_LPWSTR *DestEnd = NULL; // #typedef wchar_t *STRSAFE_LPWSTR
	size_t size = NULL;

	// 安全的字符串拼接函数 StringCchCat
	HRESULT res;
	res = StringCchCat((STRSAFE_LPWSTR)Buffer, lstrlen(Buffer) + lstrlen(LinkBuffer) + 1, (STRSAFE_LPWSTR)LinkBuffer);
	res = StringCchCatEx(
		(STRSAFE_LPWSTR)Buffer,							// 目标缓冲区
		lstrlen(Buffer) + lstrlen(LinkBuffer) + 1,		// 目标缓冲区大小,务必等于 Buffer + LinkBuffer + 1 的大小,1 为终止符
		(STRSAFE_LPWSTR)LinkBuffer,						// 源缓冲区,用于拼接至 Buffer 后
		DestEnd,										// Buffer 结尾的指针
		&size,											// 未使用的字符
		STRSAFE_NO_TRUNCATION | STRSAFE_FILL_BEHIND_NULL  // 如果函数成功,则使用dwFlags(0)的低字节来填充终止空字符后的pszDest的未初
														  // 如果函数失败,则pszDest不受影响。原始内容中没有添加任何内容
	);
	//	cout << "DestEnd: " << DestEnd << endl;
	//	cout << "size: " << size << endl;
	WCHAR DestBuffer[10] = { 0 };
	WCHAR SrcBuffer[] = L"AAAAAAAAA";
	STRSAFE_LPWSTR *DestEnd = NULL;
	size_t size = NULL;
	HRESULT res;
	res = StringCchCopy((STRSAFE_LPWSTR)DestBuffer, lstrlen(SrcBuffer) + 1, SrcBuffer);
	res = StringCchCopyEx(
		(STRSAFE_LPWSTR)DestBuffer, // 目标缓冲区 
		lstrlen(SrcBuffer) + 1,		// 目标缓冲区大小,务必等于 Buffer + LinkBuffer + 1 的大小,1 为终止符
		SrcBuffer,					// 源字符串地址
		DestEnd,					// 源字符串结尾指正
		&size,						// 目标缓冲区未使用的字节
		STRSAFE_NO_TRUNCATION | STRSAFE_FILL_BEHIND_NULL);  // 如果函数成功,则使用dwFlags(0)的低字节来填充终止空字符后的pszDest的未初始化部分
															// 与STRSAFE_NULL_ON_FAILURE的情况一样,如果函数失败,则pszDest设置为空字符串(TEXT(""))
	/*
		cout << "DestEnd: " << DestEnd << endl;
		cout << "size: " << size << endl; 
	*/
	WCHAR DestBuffer[10] = { 0 };
	HRESULT res;
	res = StringCchPrintf((STRSAFE_LPWSTR)DestBuffer, sizeof(DestBuffer) / 2, TEXT("%d + %d = %d"), 1, 2, 3);
	
	STRSAFE_LPWSTR *DestEnd = NULL;
	size_t size;
	res = StringCchPrintfEx(
		(STRSAFE_LPWSTR)DestBuffer,		// 目标缓冲区
		sizeof(DestBuffer) / 2,			// 目标缓冲区大小
		DestEnd,						// 目标缓冲区结尾指针
		&size,							// 目标缓冲区未使用的字符数
		STRSAFE_NO_TRUNCATION | STRSAFE_FILL_BEHIND_NULL,	// 如果函数成功,则使用dwFlags(0)的低字节来填充终止空字符后的pszDest的未初始化部分
															// 与STRSAFE_NULL_ON_FAILURE的情况一样,如果函数失败,则pszDest设置为空字符串(TEXT(""))
		TEXT("%d + %d = %d"), 1, 2, 3						// 格式化字符
	);
	
	if (res == S_OK)
	{
		cout << "有足够的空间可以将结果复制到pszDest而不进行截断,并且缓冲区以空值终止" << endl;
	}
	else if (res == STRSAFE_E_INSUFFICIENT_BUFFER)
	{
		cout << "cchDest 是 0 或比 STRSAFE_MAX_CCH 更大,或目标缓冲区是满的" << endl;
	}
	else if (res == STRSAFE_E_INVALID_PARAMETER)
	{
		cout << "由于缓冲区空间不足,复制操作失败" << endl;
	}
#include <Windows.h>
#include <iostream>
#include <String.h>
#include <shlwapi.h>
#pragma comment (lib, "Shlwapi.lib")
using namespace std;

int main(int argc, char *argv[])
{
	LONGLONG var_1 = 521;
	WCHAR Buffer[10] = { 0 };	// Buffer 初始化
	// StrFormatKBSize 将数值转换为字符串,该字符串表示以千字节为单位表示的大小值
	PTSTR res = StrFormatKBSize(
		var_1,					// 需要转换的数值
		(PWSTR)Buffer,			// 指向缓冲区的指针
		sizeof(Buffer) / 2	// pszBuf的大小,以字符为单位
	);
	if (res == NULL)
	{
		cout << "调用失败" << endl;
	}
	else
	{
		cout << "字符串的地址: " << res << endl;
	}
	return 0;
}
	WCHAR String1[] = L"ABCDEFG"; // 定义两个相等的字符串
	WCHAR String2[] = L"AbCdEfG";
	int res = CompareStringEx(
		LOCALE_NAME_SYSTEM_DEFAULT,					// 设置为当前操作系统区域设置的名称
		NORM_IGNORECASE | NORM_IGNORESYMBOLS,		// 忽略大小写 | 忽略符号和标点符号
		(LPCWCH)&String1,							// 用于比较的字符串 1
		sizeof(String1) / 2,						// 用于比较的字符串 1 的大小
		(LPCWCH)&String2,							// 用于比较的字符串 2
		sizeof(String2) / 2,						// 用于比较的字符串 2 的大小
		NULL,										// 保留位,必须设置为 NULL
		NULL,										// 同上
		0											// 同上
	);
	if (res != 0) // CompareStringEx 调用失败返回则 0 
	{
		switch (res)
		{
		case CSTR_LESS_THAN: 
			cout << "lpString1指示的字符串的词汇值小于lpString2指示的字符串" << endl; break;
		case CSTR_EQUAL: 
			cout << "由lpString1指示的字符串在词汇值中等效于由lpString2指示的字符串" << endl; break;
		case CSTR_GREATER_THAN: 
			cout << "lpString1指示的字符串的词汇值大于lpString2指示的字符串" << endl; break;
		}
	}
	else
	{
		DWORD error = GetLastError();
		if (error == ERROR_INVALID_FLAGS)
		{
			cout << "为标志提供的值无效: " << endl;
		}
		else if(error == ERROR_INVALID_PARAMETER)
		{
			cout << "任何参数值都无效: " << endl;
		}
	}
WCHAR String1[] = L"ABCDEFG";
	WCHAR String2[] = L"AbCdEfG";
	int res = CompareStringOrdinal((LPCWCH)String1, sizeof(String1) / 2, (LPCWCH)String2, sizeof(String2) / 2, TRUE);// TRUE 为不区分大小写的比较
	if (res != 0)
	{
		switch (res)
		{
		case CSTR_LESS_THAN:
			cout << "lpString1指示的值小于lpString2指示的值" << endl; break;
		case CSTR_EQUAL:
			cout << "lpString1指示的值等于lpString2指示的值" << endl; break;
		case CSTR_GREATER_THAN:
			cout << "lpString1指示的值大于lpString2指示的值" << endl; break;
		}
	}
	else 
	{
		DWORD res = GetLastError();
		if (res == ERROR_INVALID_PARAMETER)
		{
			cout << "任何参数值都无效" << endl;
		}
	}

	CHAR BeforeConversion[] = "ABCDEFG";
	WCHAR AfterConversion[10] = { 0 };
	int res = MultiByteToWideChar(
		CP_ACP,						// ANSI 代码页
		NULL,						// 影响读音符号的字符,一般设置为 NULL
		(LPCCH)BeforeConversion,	// 需要转换的 ANII 字符
		-1,							// 自动计算函数大小
		(LPWSTR)AfterConversion,	// 转换过后的字符串缓冲区
		sizeof(AfterConversion)		// 转换过后的字符串缓冲区的大小
	);
	if (res == 0)	// 函数调用失败返回 0
	{
		cout << "转换失败" << endl;
	}
	WCHAR BeforeConverion[] = L"ABCDEFG";
	CHAR AfterConversion[10] = { 0 };
	CHAR DefaultChar = \'*\';
	BOOL UserDefaultChar = NULL;
	int res = WideCharToMultiByte(
		CP_UTF8,					// 使用 CP_UTF8 代码页完成从宽字节到多字节的转换
		NULL,						// 一般为 NULL
		(LPCWCH)BeforeConverion,	// 需要转换的字符串的地址
		-1,							// 自动计算转换字符串的大小
		(LPSTR)AfterConversion,		// 转换完成时字符串储存地址
		sizeof(AfterConversion),	// 储存地址大小
		(LPCCH)DefaultChar,			// 遇到无法转换的字符时用什么代替
		(LPBOOL)UserDefaultChar		// 转换成功返回 FALSE,有一个或者多个字符无法转换时设置为 TRUE
	);
	if (res != 0 && UserDefaultChar == FALSE) 
	{
		cout << "转换成功" << endl;
	}
	else // 调用之后返回 0 表示失败
	{
		switch (res)
		{
		case ERROR_INSUFFICIENT_BUFFER:
			cout << "提供的缓冲区大小不够大,或者错误地设置为NULL" << endl; break;
		case ERROR_INVALID_FLAGS:
			cout << "为标志提供的值无效" << endl; break;
		case ERROR_INVALID_PARAMETER:
			cout << "任何参数值都无效" << endl; break;
		case ERROR_NO_UNICODE_TRANSLATION:
			cout << "在字符串中找到无效的Unicode" << endl; break;
		}
	}
  • IsTextUnicode(用于判断是 ANSI 字符还是宽字节字符)
	CHAR JudgeStr[] = "ABCDEFG"; // 测试字符串
	int Result = IS_TEXT_UNICODE_REVERSE_MASK; // 是否包含宽字界字符标志位
	BOOL res = IsTextUnicode((const void *)JudgeStr, sizeof(JudgeStr), (LPINT)&Result);
	if (res != 0)
	{
		cout << "包含宽字节字符" << endl;
	}
	else
	{
		cout << "为 ANSI 字符" << endl;
	}

版权声明:本文为csnd原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/csnd/p/11800528.html