• Windows核心编程笔记之处理字符串


    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;
    	}
    
  • 相关阅读:
    小组最终答辩
    机器学习的安全隐私
    关于Distillation as a Defense to Adversarial Perturbations against Deep Neural Networks的理解
    第十六讲-对抗样本与对抗训练3
    对抗样本机器学习_Note1_机器学习
    对抗样本机器学习_cleverhans_FGSM/JSMA
    实验四:Tensorflow实现了四个对抗图像制作算法--readme
    实验一拓展文献阅读—反向传播计算图上的微积分
    tf.placeholder 与 tf.Variable
    Robust Adversarial Examples_鲁棒的对抗样本
  • 原文地址:https://www.cnblogs.com/csnd/p/11800528.html
Copyright © 2020-2023  润新知