[笔记]Windows核心编程《一》错误处理、字符编码

简介: Windows核心编程《一》错误处理、字符编码

系列文章目录



[笔记]Windows核心编程《一》错误处理、字符编码

[笔记]Windows核心编程《二》内核对象

[笔记]Windows核心编程《三》进程

[笔记]Windows核心编程《四》作业

[笔记]快乐的LInux命令行《五》什么是shell

[笔记]Windows核心编程《五》线程基础

[笔记]Windows核心编程《六》线程调度、优先级和关联性

[笔记]Windows核心编程《七》用户模式下的线程同步

[笔记]Windows核心编程《八》用内核对象进行线程同步

[笔记]Windows核心编程《九》同步设备I/O和异步设备I/O

[笔记]Windows核心编程《十一》Windows线程池

[笔记]Windows核心编程《十二》纤程

[笔记]Windows核心编程《十三》windows内存体系结构

[笔记]Windows核心编程《十四》探索虚拟内存

[笔记]Windows核心编程《十五》在应用程序中使用虚拟内存

[笔记]Windows核心编程《十六》线程栈

[笔记]Windows核心编程《十七》内存映射文件

[笔记]Windows核心编程《十八》堆栈

[笔记]Windows核心编程《十九》DLL基础

[笔记]Windows核心编程《二十》DLL的高级操作技术

[笔记]Windows核心编程《二十一》线程本地存储器TLS

[笔记]Windows核心编程《二十二》注入DLL和拦截API

[笔记]Windows核心编程《二十三》结构化异常处理


文章目录



   系列文章目录

   前言

   一、错误处理

       1.1 strerror(errno)

       1.2 _set_errno(0)

       1.3 GetLastError

       1.4 FormatMessage()

       1.5 LocalLock/LocalFree

   二、Windows函数常见返回值的意义

   三、字符和字符串处理

       3.1字符编码

           3.1.1 ASCII字符集(多字节字符集)

           3.1.2 UNICODE字符集

               a.字符编码

           3.1.3 常见关于字符编码的宏

           3.1.4字符串处理

               a.字符串函数

           3.1.5 代码实战

   四、代码页

   总结

           小技巧


前言


windows核心编程


一、错误处理



1.1 strerror(errno)

string.h

解析全局errno变量的含义 转成字符串


1.2 _set_errno(0)

string.h

字面意思 设置全局错误码


1.3 GetLastError

windows.h

GetLastError() 获取错误码


1.4 FormatMessage()

windows.h

将GetLastError获得的错误码转化为字符串信息

从系统中获取错误码
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, 0, NULL, str, 200, NULL);
从模块中获取错误码
HMOUDLE hMoudle = LoadLibrary(L"user32.dll");
FormatMessage(
FORMAT_MESSAGE_FROM_MODULE | FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_ALLOCATE_BUFFER,
hModule, 0, NULL, str, 200, NULL);
// FORMAT_MESSAGE_ALLOCATE_BUFFER 自动分配内存

1.5 LocalLock/LocalFree

锁定本地内存与销毁内存,一般用于函数自动分配的内存。


二、Windows函数常见返回值的意义


VOID:这个函数不可能失败!

BOOL:FALSE失败;TRUE成功。

HANDLE:失败返回NULL,否则返回非零句柄。如果有特殊说明,则可能为特殊值例如:INVALID_HANDLE_VALUE。

PVOID:返回一个内存地址,失败为NULL

LONG/DWORD:应该根据SDK说明来确定函数状况。


三、字符和字符串处理


3.1字符编码

3.1.1 ASCII字符集(多字节字符集)

ASCII 字符集在 0x00 - 0x7F 范围内定义字符。 还有许多其他字符集(主要是欧洲字符集),它们在 0x00 - 0x7F

范围内定义与 ASCII 字符集相同的字符,还在 0x80 - 0xFF. 范围内定义扩展字符集。 (SBCS) 的8位单字节字符集足以表示 ASCII 字符集以及许多欧洲语言的字符集,这一点非常好。

但是,一些非欧洲字符集(如日本汉字)包含的字符数多于单字节编码方案可表示的字符数,因此需要多字节字符集 (MBCS) 编码。

多字节字符集可以包含单字节和双字节字符。

多字节字符字符串可以包含单字节字符和双字节字符的组合。

两字节多字节字符具有一个前导字节和一个尾字节。

在特定的多字节字符集中,前导字节位于某个范围内,尾字节也是如此。

当这些范围重叠时,可能需要计算上下文,以确定给定的字节是用作前导字节还是尾字节。


3.1.2 UNICODE字符集

UNICODE字符,什么是UNICODE字符,为什么要有UNICODE字符??

a.字符编码

UTF-8:

一个字节一个字符,有些字符是2个字节,有的字符是3个字节,还有的字符是4个字节。

UTF-16

大部分字符都是2个字节,一般UNICODE就是指utf-16,

Windows的Unicode编码一般指utf-16,然后Java的String一般也是Utf-16编码。

UTF-32

所有字符都是4个字节。一般非Windows平台。


3.1.3 常见关于字符编码的宏

TEXT()

_T()

TCHAR 字符类型

UNICODE 判断是否UNICODE编码的宏


WIN32 表示跨平台时使用,如果一个工程使用了windows api,那么它在引入windows api相关的头文件后,必须预定义WIN32以启用WIN32API

_WIN64 表示编译时使用,同_WIN32,只不过此编译选项编出来的代码只能在 64位机器上运行。

_WIN32 表示编译时使用,用来指定编译器的编译结果可以在哪种架构上运行,如果是_WIN32,则既可以在 x86上 又可以在 x64上运行,此外还可以在ARM32和ARM64上运行,简言之,编出来的代码可以同时在 32位机器和64位机器上运行。


3.1.4字符串处理

a.字符串函数

1. 包含宽字符和窄字符处理

例如_tcslen(),

定义多字节宏 _MBCS 则使用strlen()

定义Unicode宏_UNICODE 则使用wcslen()


2.StringSafe.h包含安全字符串处理

我们编程的时候,尽量使用安全字符串,

strcpy(dst,src)->strcpy_s(dst,srcLen,src)

而StringSafe.h中包含不少可以安全处理字符串的函数

HRESULT StringCchCat(
  __inout  LPTSTR pszDest,
  __in     size_t cchDest,
  __in     LPCTSTR pszSrc
);
pszDest:目标字符串;
cchDest:目标字符串内存大小;
pszSrc: 源字符串。
这是一个字符串拷贝函数,在strsafe.h中。
HRESULT StringCchPrintf(
  __out  LPTSTR pszDest,
  __in   size_t cchDest,//目标内存大小
  __in   LPCTSTR pszFormat,
  __in    ...
);
这个函数和printf函数用法类似,只是将字符写入了pszDest内存块中,而不是屏幕上!

Windows.h中 字符串比较函数

int CompareString(
  __in  LCID Locale,
  __in  DWORD dwCmpFlags,
  __in  LPCTSTR lpString1,
  __in  int cchCount1,
  __in  LPCTSTR lpString2,
  __in  int cchCount2
);
int CompareStringOrdinal(
  __in  LPCWSTR lpString1,
  __in  int cchCount1,
  __in  LPCWSTR lpString2,
  __in  int cchCount2,
  __in  BOOL bIgnoreCase
);
第二个和语言无关,速度更快!!!建议使用!!!

3.ASCII 和 UNICODE 之间的字符转换

int MultiByteToWideChar(
  __in   UINT CodePage,
  __in   DWORD dwFlags,
  __in   LPCSTR lpMultiByteStr,
  __in   int cbMultiByte,
  __out  LPWSTR lpWideCharStr,
  __in   int cchWideChar
);
int WideCharToMultiByte(
  __in   UINT CodePage,
  __in   DWORD dwFlags,
  __in   LPCWSTR lpWideCharStr,
  __in   int cchWideChar,
  __out  LPSTR lpMultiByteStr,
  __in   int cbMultiByte,
  __in   LPCSTR lpDefaultChar,
  __out  LPBOOL lpUsedDefaultChar
);
BOOL IsTextUnicode(
  __in     const VOID *lpv,
  __in     int iSize,
  __inout  LPINT lpiResult
);


3.1.5 代码实战

1.vs下使用printf/wsprintf 打印中文的宽字符%S和窄字符%s

#include <stdio.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>
void main() {
  setlocale(LC_ALL, "");
  wchar_t wszName[] = L"WCHAR中文TEST";
  char szName[] = "CHAR汉语测试TEST";
    printf("szWchar = %S, length = %d\n", wszName, wcslen(wszName));
    printf("szChar = %s, length = %d\n", szName, strlen(szName));
    wprintf(L"wprintf szWchar = %s\n", wszName);
    wprintf(L"wprintf szChar = %S\n", szName);
}

2.使用StringCchPrintf/StringCchCat/StringCchCopy

char mem[1000] = {0};
StringCchPrintf(mem, 1000, "%d,%s", 10, "helloworld");
StringCchCat(mem, 1000, "你好");//追加
StringCchCopy(mem, 1000, "您好");//拷贝

3.使用CompareString/CompareStringOriginal

TCHAR szBuffer[10] = {
    TEXT('A'),TEXT('A'),TEXT('A'),TEXT('A'),TEXT('A'),
    TEXT('A'),TEXT('A'),TEXT('A'),TEXT('B'),'\0'
  };
    LCID local = GetThreadLocale();
    //int result = CompareString(local/*LOCALE_SYSTEM_DEFAULT*/, NORM_IGNORECASE, szBuffer, _countof(szBuffer), TEXT("AAAAAAAAA"), 10);
  int result = CompareStringOrdinal(L"AAAAAAAAB", 10, L"AAAAAAAAA", 10, TRUE);
  switch (result)
  {
  case 0:
    cout << "Error" << endl;
    break;
  case CSTR_LESS_THAN:
    cout << "Str1 《 Str2" << endl;
    break;
  case CSTR_GREATER_THAN:
    cout << "Str1 》 Str2" << endl;
    break;
  case CSTR_EQUAL:
    cout << "Str1 = Str2" << endl;
    break;
  default:
    cout << "Don't goto there" << endl;
    break;
  }

4.使用IsTextUnicode判断

if (IsTextUnicode(L"abc", 4, NULL)) {
  printf("is unicode");
}
else {
  printf("is ascii code");
}

5.多字节和UNICODE转换

void main2() {
    char sBuf[25] = { 0 };
    strcpy_s(sBuf,25, "我最棒");
    //获取输入缓存大小
    int sBufSize = strlen(sBuf);
    //获取输出缓存大小
    //VC++ 默认使用ANSI,故取第一个参数为CP_ACP
    DWORD dBufSize = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, NULL, 0);
    printf("需要wchar_t%u个\n", dBufSize);
    wchar_t* dBuf = new wchar_t[dBufSize];
    wmemset(dBuf, 0, dBufSize);
    //进行转换
    int nRet = MultiByteToWideChar(CP_ACP, 0, sBuf, sBufSize, dBuf, dBufSize);
    if (nRet <= 0)
    {
        cout << "转换失败" << endl;
        DWORD dwErr = GetLastError();
        switch (dwErr)
        {
        case ERROR_INSUFFICIENT_BUFFER:
            printf("ERROR_INSUFFICIENT_BUFFER\n");
            break;
        case ERROR_INVALID_FLAGS:
            printf("ERROR_INVALID_FLAGS\n");
            break;
        case ERROR_INVALID_PARAMETER:
            printf("ERROR_INVALID_PARAMETER\n");
            break;
        case ERROR_NO_UNICODE_TRANSLATION:
            printf("ERROR_NO_UNICODE_TRANSLATION\n");
            break;
        }
    }
    else
    {
        cout << "转换成功" << endl;
        cout << dBuf;
    }
    delete(dBuf);
}
void main(){
    //从宽字符串转换窄字符串
    wchar_t sBuf[25] = { 0 };
    wcscpy_s(sBuf,100, L"我最棒");
    //获取转换所需的目标缓存大小
    DWORD dBufSize = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, NULL, 0, NULL, FALSE);
    //分配目标缓存
    char* dBuf = new char[dBufSize];
    memset(dBuf, 0, dBufSize);
    //转换
    int nRet = WideCharToMultiByte(CP_OEMCP, 0, sBuf, -1, dBuf, dBufSize, NULL, FALSE);
    if (nRet <= 0)
    {
        printf("转换失败\n");
    }
    else
    {
        printf("转换成功\nAfter Convert: %s\n", dBuf);
    }
    delete[]dBuf;
}


四、代码页


代码页通常和软件本地化 多语言支持有关。

https://www.cnblogs.com/benbenalin/p/6911781.html

https://www.cnblogs.com/benbenalin/p/6907907.html

https://www.cnblogs.com/benbenalin/p/6915513.html


总结


小技巧

1.vs

选中函数 按下f1 可进入msdn网页 函数具体详情

2.vs

F5运行,Cirl+F5 无调试运行,F7编译,

3.工具栏-》错误查找 工具可以查找错误码对应的错误含义


相关文章
|
2月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
83 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
3月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
3月前
|
Windows
[原创]用MASM32编程获取windows类型
[原创]用MASM32编程获取windows类型
|
3月前
|
JavaScript 前端开发 API
MASM32编程通过WMI获取Windows计划任务
MASM32编程通过WMI获取Windows计划任务
|
3月前
|
API Windows
MASM32编程获取Windows当前桌面主题名
MASM32编程获取Windows当前桌面主题名
|
3月前
|
关系型数据库 数据库 PostgreSQL
在C#中获取与设置Windows的字符编码方式
通过以上步骤,你可以在Docker环境下有效地重启PostgreSQL服务。这对于维护数据库健康、应用更新或环境配置更改后确保数据库服务正常运行至关重要。根据你的具体需求和环境设置,选择合适的方法来执行重启操作。
22 0
|
4月前
|
编译器 开发工具 C语言
解锁QtCreator跨界神技!Windows下轻松驾驭OpenCV动态库,让你的跨平台开发如虎添翼,秒变视觉编程大师!
【8月更文挑战第4天】QtCreator是一款强大的跨平台IDE,便于创建多平台应用。本教程教你如何在Windows环境下集成OpenCV库至Qt项目。首先,下载匹配MinGW的OpenCV预编译版并解压。接着,在QtCreator中新建或打开项目,并在.pro文件中添加OpenCV的头文件和库文件路径。确保编译器设置正确。随后编写测试代码,例如加载和显示图片,并进行编译运行。完成这些步骤后,你就能在QtCreator中利用OpenCV进行图像处理开发了。
260 6
|
5月前
|
Linux Apache C++
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
该文介绍了如何在Windows环境下为FFmpeg集成SRT协议支持库libsrt。首先,需要安装Perl和Nasm,然后编译OpenSSL。接着,下载libsrt源码并使用CMake配置,生成VS工程并编译生成srt.dll和srt.lib。最后,将编译出的库文件和头文件按照特定目录结构放置,并更新环境变量,重新配置启用libsrt的FFmpeg并进行编译安装。该过程有助于优化直播推流的性能,减少卡顿问题。
143 2
FFmpeg开发笔记(三十五)Windows环境给FFmpeg集成libsrt
|
4月前
|
数据库 Windows
超详细步骤解析:从零开始,手把手教你使用 Visual Studio 打造你的第一个 Windows Forms 应用程序,菜鸟也能轻松上手的编程入门指南来了!
【8月更文挑战第31天】创建你的第一个Windows Forms (WinForms) 应用程序是一个激动人心的过程,尤其适合编程新手。本指南将带你逐步完成一个简单WinForms 应用的开发。首先,在Visual Studio 中创建一个“Windows Forms App (.NET)”项目,命名为“我的第一个WinForms 应用”。接着,在空白窗体中添加一个按钮和一个标签控件,并设置按钮文本为“点击我”。然后,为按钮添加点击事件处理程序`button1_Click`,实现点击按钮后更新标签文本为“你好,你刚刚点击了按钮!”。
351 0
|
5月前
|
存储 安全 数据安全/隐私保护
Windows 32 汇编笔记(一):基础知识
Windows 32 汇编笔记(一):基础知识