转载:https://blog.csdn.net/mousebaby808/article/details/5259944

并不是所有的Windows操作系统都支持UNICODE编码的API(例如早期的Windows98), 这就造成了两种结果:某些版本的Windows应该应用wchar_t来保存字符, 某些平台的Windows应该使用char类型来保存字符, 显然这两种类型的变量是无法混用的。

  为了解决该问题, Windows从一开始设计Windows时, 就提供了一整套方案, 对于支持ASCII字符集的API函数, 函数使用字母A作为后缀;对于支持UNICODE字符集的API函数, 则使用字母W作为后缀。例如:FormatMessage函数就提供了FormatMessageA和FormatMessageW两个版本。

  文档记载及我们使用的API函数, 实际是定义在Windows.h文件中的一组“宏”, 这组宏在UNICODE环境下将调用函数映射为后缀为W的函数;在ASCII环境下将调用函数映射为后缀为A的函数。

  tchar.h头文件提供了一个数据类型TCHAR, 这个类型在UNICODE环境下将映射为wchar_t类型;在ASCII环境下映射为char类型。另外, tchar.h还提供了一组C语言字符串操作符的替代宏, 以_t开头, 例如_tcslen函数, 在UNICODE环境下被映射成为wcslen函数, 在ASCII环境下被映射成为strlen函数。

  最后, tchar.h提供了_T宏, 该宏具有一个字符串类型参数, 在UNICODE环境下, 该宏会为字符串前面加上L符号。

  1.  
    // 定义宏UNICODE和_UNICODE, 一旦定义了该宏, C语言编译器将在UNICODE环境下工作
  2.  
    // 注意, 一般情况下需要定义UNICODE宏和_UNICODE宏, 因为不同版本的C编译器要求不同
  3.  
     
  4.  
    // 在正式工作时, 并不需要定义这两个宏, 只需要在"项目属性->配置属性->字符集"中选择
  5.  
    // UNICODE字符集或是多字节字符集即可, 开发环境会自动定义相应的宏
  6.  
    #if !defined(UNICODE)
  7.  
    #define UNICODE
  8.  
    #endif
  9.  
     
  10.  
    #if !defined(_UNICODE)
  11.  
    #define _UNICODE
  12.  
    #endif
  13.  
     
  14.  
    // 在所有头文件之前包含tchar.h头文件
  15.  
    // 这是程序可以应用各类替代宏的基础
  16.  
    #include <tchar.h>
  17.  
    #include <locale.h>
  18.  
    #include <stdio.h>
  19.  
    #include <stdlib.h>
  20.  
    #include <windows.h>
  21.  
     
  22.  
    /**
  23.  
    * 显示一个字符, ASCII版本
  24.  
    * 参数:c, 要显示的字符变量
  25.  
    */
  26.  
    void ShowCharacterA(char c)
  27.  
    {
  28.  
    // 在ASCII版本中, 选用printf函数来显示字符串
  29.  
    printf("(A)字符 %c 占据空间 %d", c, sizeof(c));
  30.  
    }
  31.  
     
  32.  
    /**
  33.  
    * 显示一个字符, UNICODE版本
  34.  
    * 参数:c, 要显示的字符变量
  35.  
    */
  36.  
    void ShowCharacterW(wchar_t wc)
  37.  
    {
  38.  
    // 在UNICODE版本中, 选用wprintf函数来显示UNICODE字符串
  39.  
    wprintf(L"(W)字符 %c 占据空间 %d", wc, sizeof(wc));
  40.  
    }
  41.  
     
  42.  
    /**
  43.  
    * 显示一个字符串, ASCII版本
  44.  
    * 参数:lpcsz, 要显示的字符变量
  45.  
    */
  46.  
    void ShowStringA(const char* lpcsz)
  47.  
    {
  48.  
    // 在ASCII版本中, 选用printf函数来显示ASCII字符串,
  49.  
    // 选用strlen函数来测量字符串长度
  50.  
    printf("/n(A)字符串 %s 长度为%d", lpcsz, strlen(lpcsz));
  51.  
    }
  52.  
     
  53.  
    /**
  54.  
    * 显示一个字符串, UNICODE版本
  55.  
    * 参数:lpcwsz, 要显示的字符变量
  56.  
    */
  57.  
    void ShowStringW(const wchar_t* lpcwsz)
  58.  
    {
  59.  
    // 在UNICODE版本中, 选用wprintf函数来显示UNICODE字符串,
  60.  
    // 选用wcslen函数来测量字符串长度
  61.  
    wprintf(L"/n(W)字符串 %s 长度为%d", lpcwsz, wcslen(lpcwsz));
  62.  
    }
  63.  
     
  64.  
     
  65.  
     
  66.  
     
  67.  
    // 下面这一组编译器指令, 根据是否定义UNICODE(或_UNICODE)宏, 映射不同的函数
  68.  
    // 可以删除#if和#endif之间的代码, 查看运行结果的变化, 思考产生这种变化的原因
  69.  
    #if defined(UNICODE) | defined(_UNICODE)
  70.  
     
  71.  
    // 定义ShowCharacter宏映射到ShowCharacterW函数
  72.  
    #define ShowCharacter ShowCharacterW
  73.  
     
  74.  
    // 定义ShowString宏映射到ShowStringW函数
  75.  
    #define ShowString ShowStringW
  76.  
     
  77.  
    #else
  78.  
     
  79.  
    // 定义ShowCharacter宏映射到ShowCharacterA函数
  80.  
    #define ShowCharacter ShowCharacterA
  81.  
     
  82.  
    // 定义ShowString宏映射到ShowStringA函数
  83.  
    #define ShowString ShowStringA
  84.  
     
  85.  
    #endif
  86.  
     
  87.  
     
  88.  
     
  89.  
    // 定义缓冲区长度为512个字符
  90.  
    #define BUF_LEN 512
  91.  
     
  92.  
    int _tmain(int argc, TCHAR* argv[])
  93.  
    {
  94.  
    // 定义变量, 保存字符
  95.  
    TCHAR c = _T('A');
  96.  
     
  97.  
    // 定义字符数组, 保存字符串
  98.  
    TCHAR szStr[] = _T("ABC大家好");
  99.  
     
  100.  
    // 定义指向字符串的指针
  101.  
    TCHAR* lpszStr = _T("Hello你好");
  102.  
     
  103.  
    // 定义指向字符串的常量指针
  104.  
    const TCHAR* lpcszStr = _T("GoodBye再见");
  105.  
     
  106.  
    int bSame;
  107.  
     
  108.  
    // 定义BUF_LEN长度的字符数组作为缓冲区
  109.  
    TCHAR szBuffer[BUF_LEN] = _T("");
  110.  
     
  111.  
    // 定义ASCII字符集缓冲区
  112.  
    char szBufferA[BUF_LEN] = "";
  113.  
     
  114.  
    // 定义UNICODE字符集缓冲区
  115.  
    wchar_t szBufferW[BUF_LEN] = L"";
  116.  
     
  117.  
    // 定义错误代码22
  118.  
    const int nError = 22;
  119.  
     
  120.  
    // 设置语言环境为中文
  121.  
    _tsetlocale(LC_ALL, _T("zhi"));
  122.  
     
  123.  
    // 调用ShowCharacter宏
  124.  
    ShowCharacter(c);
  125.  
     
  126.  
    // 调用ShowCharacter宏
  127.  
    ShowString(szStr);
  128.  
    ShowString(lpszStr);
  129.  
    ShowString(lpcszStr);
  130.  
     
  131.  
    // _tcsicmp是tchar.h中定义的宏,
  132.  
    // 在不同的字符集环境下映射为stricmp或wcsicmp函数
  133.  
    bSame = _tcsicmp(lpszStr, lpcszStr);
  134.  
     
  135.  
    if (bSame == 0)
  136.  
    {
  137.  
    // _tprintf是tchar.h中定义的宏, 在不同字符集环境下映射为printf或wprintf函数
  138.  
    _tprintf(_T("/n字符串 %s 与 %s 相同"), lpszStr, lpcszStr);
  139.  
    }
  140.  
    else
  141.  
    _tprintf(_T("/n字符串 %s 与 %s 不同"), lpszStr, lpcszStr);
  142.  
     
  143.  
    // _tcscpy_s是tchar.h中定义的宏,
  144.  
    // 在不同字符集环境下映射为strcpy_s或wcscpy_s函数(_s表示安全版本函数)
  145.  
    _tcscpy_s(szBuffer, BUF_LEN, lpszStr);
  146.  
     
  147.  
    // _tcscat_s是tchar.h中定义的宏,
  148.  
    // 在不同字符集环境下映射为strcat_s或wcscat_s函数(_s表示安全版本函数)
  149.  
    _tcscat_s(szBuffer, BUF_LEN, lpcszStr);
  150.  
     
  151.  
    // _tcslen是tchar.h中定义的宏,
  152.  
    // 在不同字符集环境下映射为strlen或wcslen函数
  153.  
    _tprintf(_T("/n字符串 %s 长度为 %d"), szBuffer, _tcslen(szBuffer));
  154.  
     
  155.  
    // 接下来, 我们看一下FormatMessage函数在不同环境下的应用
  156.  
     
  157.  
    // ASCII环境下应用, 第5个参数使用char类型数组作为缓冲
  158.  
    FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nError, 0, szBufferA, BUF_LEN, NULL);
  159.  
    printf("/n错误信息:%s", szBufferA);
  160.  
     
  161.  
    // UNICODE环境下应用, 第5个参数使用wchar_t类型数组作为缓冲
  162.  
    FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nError, 0, szBufferW, BUF_LEN, NULL);
  163.  
    wprintf(L"错误信息:%s", szBufferW);
  164.  
     
  165.  
    // 自适应环境, 第5个参数使用TCHAR类型数组作为缓冲
  166.  
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, nError, 0, szBuffer, BUF_LEN, NULL);
  167.  
    _tprintf(_T("错误信息:%s"), szBuffer);
  168.  
     
  169.  
    _tprintf(_T("/n"));
  170.  
    system("pause");
  171.  
    return 0;
  172.  
    }

TCHAR数据类型介绍的更多相关文章

  1. Redis常用数据类型介绍、使用场景及其操作命令

    Redis常用数据类型介绍.使用场景及其操作命令 本文章同时也在cpper.info发布. Redis目前支持5种数据类型,分别是: 1.String(字符串) 2.List(列表) 3.Hash(字 ...

  2. Hadoop数据类型介绍

    我们知道hadoop是由Java 编程写的.因此我们使用Java开发环境来操作HDFS,编写mapreduce也是很自然的事情.但是这里面hadoop却对Java数据类型进行了包装,那么hadoop的 ...

  3. C 各种数据类型介绍

    1.各种数据类型介绍: 基本数据类型最主要的特点是,其值不可以再分解为其它类型.也就是说,基本数据类型是自我说明的. 1.1整型 整形包括短整型.整形和长整形. 1.1.1短整形 short a=1; ...

  4. 以太坊智能合约 Solidity 的常用数据类型介绍

    目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...

  5. MySQL:数据类型介绍

    数据类型介绍 一.整数类型(可以添加自增约束条件) 数据类型 存储需要 有符号 无符号 tinyint 1个字节 -2^7~2^7-1 0~2^8 smallint 2个字节 -2^15~2^15-1 ...

  6. openresty开发系列13--lua基础语法2常用数据类型介绍

    openresty开发系列13--lua基础语法2常用数据类型介绍 一)boolean(布尔)布尔类型,可选值 true/false: Lua 中 nil 和 false 为"假" ...

  7. SQL数据类型介绍

    在计算机中数据有两种特征:类型和长度.所谓数据类型就是以数据的表现方式和存储方式来划分的数据的种类.    在SQL Server 中每个变量.参数.表达式等都有数据类型.系统提供的数据类型分为几大类 ...

  8. mysql数据类型介绍

    一.int.bigint.smallint 和 tinyint的区别详细介绍 bigint 从 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854 ...

  9. MySQL 中的数据类型介绍(转)

    据我统计,MySQL支持39种(按可使用的类型字段统计,即同义词也作多个)数据类型.下面的介绍可能在非常古老的mysql版本中不适用. 转载出处:http://blog.csdn.net/anxpp/ ...

随机推荐

  1. 【小白学PyTorch】1 搭建一个超简单的网络

    文章目录: 目录 1 任务 2 实现思路 3 实现过程 3.1 引入必要库 3.2 创建训练集 3.3 搭建网络 3.4 设置优化器 3.5 训练网络 3.6 测试 1 任务 首先说下我们要搭建的网络 ...

  2. Lct 动态链接树

    通过树链剖分能了解轻重边 Acdreamer 的博客 http://blog.csdn.net/acdreamers/article/details/10591443 然后看杨哲大大的论文,能了解轻重 ...

  3. CSDN自定义栏目代码

    今天终于发现了csdn可以操作的地方,有个自定义栏目的地方可以贴HTML代码(只允许最多一个自定义栏目),不能用JS插件 有点难受,就贴了下自己的微信,并且可以直接点击图片发起会话 以下是我的代码,可 ...

  4. Linux—账号管理及命令使用详解

    关注微信公众号:CodingTechWork,一起学习进步. 引言   在Linux系统中,我们常常会看到目录或文件的所属关系: [root@linux01 ~]# ll -d test.sh -rw ...

  5. Zabbix value cache working in low memory mode

    Zabbix监控自身时告警"Zabbix value cache working in low memory mode",出现这个问题是因为Zabbix Server的参数Valu ...

  6. CVE-2020-0796(永恒之黑)漏洞复现

    声明:仅供学习与参考,请勿用于非法用途(后果自负) 一.影响范围(需关闭 Win10 防火墙): Windows 10 Version 1903 for 32-bit Systems Windows ...

  7. 操作DOM对象

    操作DOM对象 目录 操作DOM对象 1. 核心 2. 获得Dom节点 3. 更新节点 1. 操作文本 2. 操作CSS 4. 删除节点 5. 插入节点 1. 追加(将已存在的节点移到后面) 2. 创 ...

  8. centos7使用Minikube“快速搭建“出Kubernetes本地实验环境(踩坑集锦及解决方案)

    先决条件(先假设你做完这两步骤) 检查Linux是否支持虚拟化,验证输出是否为非空如何开启虚拟化 grep -E --color 'vmx|svm' /proc/cpuinfo 安装 kubectl ...

  9. python中使用token模拟登录

    背景:在接口测试中我们经常是需要一个登陆token,或者获取其他用到的参数来关联下一个接口用到的参数. Token的意义及用法 一.Token的来源: 当客户端多次向服务端请求数据时,服务端就需要多次 ...

  10. STL-Deque(双端队列)与单调队列的实现

    前言: STl是个好东西,虽然他在不开O2的条件下会跑的很慢,但他着实会让你的代码可读性大大提高,令你的代码看起来既简单又整洁. 双端队列: 顾名思义,双端队列是有两个头的,一个队首指针,一个队尾指针 ...