宽字符wchar_t和窄字符char——putwchar、wprintf

宽字符wchar_t 与 窄字符char

先说下窄字符char,这个大部分读者应该很清楚,char类型的变量占一个字节(byte)(也就是8个bit(比特)),能表示256个字符,那char的范围有两种

第一种(signed char):-128~127

第二种(unsigned char):0~255

(对char的范围感兴趣的读者可以看一下这篇文章:浅谈char类型范围

但C标准并没有规定char 应该是unsigned还是signed,C标准定义了三种类型:char、signed char、unsigned char在不同的编译器下char可能是有符号数,也有可能是无符号数(意思是取决于编译器

那么怎样确定char是有符号数还是无符号数呢,有两种方法

方法一:使用CHAR_MIN(注意:CHAR_MIN这个宏是在stdlib.h这个头文件中定义的)

运行结果:

方法二:给char类型的变量赋值负数(如果char在编译器上是有符号数,那么赋值只要是大于等于-128的数都可以正常打印)

运行结果:

上述两种方法都可以用来确定char是无符号数还是有符号数(感兴趣的读者可以自行测试一下char的边界,如果char是有符号数,可以给char赋值127或128来看一下会出现什么结果)

现在来说下宽字符wchar_t,先来看下char和wchar_t在存储空间上的差别

运行结果:

从上面可以看出char占一个字节,wchar_t占两个字节

下面来确定wchar_t是有符号数还是无符号数

运行结果:

从上面的结果可以看出wchar_t为无符号数,因为wchar_t占两个字节,也就是16个比特(bit),最大值就是216-1=65535,到这里读者可以看出宽字符和窄字符最大的区别就是占字节大小的不同

宽字符 和 窄字符的赋值

关于窄字符char,大部分读者都知道赋值的方法或者

而宽字符的赋值就不太一样与窄字符相比,前面多了一个大写的L,这个L的作用就是告诉编译器,这个字符串按照宽字符来存储(一个字符占两个字节)

按照之前的说法宽字符中一个字符占2个字节,那么mm[20]应该占40个字节,长度应该为11,下面来验证一下

运行结果:

上面的代码中用到了一个函数wcslen(),这个函数和strlen()其实是一个作用,只不过strlen适用于窄字符,wcslen适用于宽字符(读者可以理解为wcslen是strlen对应的一个宽字符版本函数)

在C语言中的每个字符串处理函数都有对应的宽字符处理版本,下面列举一些常见的宽字符处理函数

(图片出处:https://www.cnblogs.com/mr-wid/archive/2012/10/07/2714392.html)

还有一点需要读者注意的是,宽字符不等于Unicode,Unicode 是宽字符编码的一种,只不过最常见的宽字符编码方式就是Unicode了,UTF-16和UTF-32都是Unicode编码。wchar_t也主要以这两种方式实现

( c/c++标准只是声明wchar_t是一个足够宽的变量类型,可以表示字符集中的任意一个字符)

Unicode 是一套字符集,而不是一套字符编码,严格来说,字符集和字符编码不是一个概念:

字符集定义了字符和二进制的对应关系,为每个字符分配了唯一的编号。可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,

计算机显示文字或者存储文字,就是一个查表的过程。

而字符编码规定了如何将字符的编号存储到计算机中。如果使用了类似 GB2312 和 GBK 的变长存储方案(不同的字符占用的字节数不一样),那么为了区分一个字符

到底使用了几个字节,就不能将字符的编号直接存储到计算机中,字符编号在存储之前必须要经过转换,在读取时还要再逆向转换一次,这套转换方案就叫做字符编码

Unicode最长是32位,也就是4个字节,因为UTF-8是1~6个字节来存储,当使用5或6字节存储时,就不属于Unicode编码了

(感兴趣的读者可以看一下:刨根问底:C++中宽字符类型(wchar_t)的编码一定是Unicode?长度一定是16位?

宽字符输出函数

wprintf

wprintf无非就是printf的一个变种,和fprintf差不多只是格式上稍有区别

运行结果:

上面的代码中,wprintf使用的格式控制符是%ls,%ls意味着将对应的参数会被当作基于宽字符的字符串(wide chraracter string )看待,而%s则意味着对应的参数会被当作普通字符串(multi-byte string)看待,

不要因为上面一句话而错误的认为%s只用于printf,而%ls只用于wprintf,其实在windows下使用都是可以正常输出宽字符串的(其他操作系统下就不一定了)

%s
当使用 printf() 时,按照单字符格式输出字符串
当使用 wprintf() 时,按照宽字符(两字节)格式输出字符串

%S
当使用 printf() 时,按照宽字符格式输出字符串
当使用 wprintf() 时,按照单字符格式输出字符串

注意这个H是宽字符串mm中的H,而不是ss中的H,ss中的字符串中的每个字符占一个字节,printf如果按照宽字符的标准来输出就无法正常输出了,而wprintf为什么只输出了H呢,不是输出字符串吗,

下面我们用VS来看宽字符在内存中的存储

从上图就可以很清楚的看出“Hello World”这个宽字符串在内存中的存储情况了,因为是宽字符所以大写字母H用两个字节表示(48 00),48是16进制转成10进制就是72,刚好就是‘H‘的ASCII码值的大小,如果按照单字符格式输出(也就是一个字节一个字节的输出)就输出H,继续往后,编译器看到第二个字节00,就以为字符串已经到结束了,最后我们看到的结果就是只输出了大写字符H

如果想要输出宽字符的单个字符,需要使用格式控制符%lc

(要清楚%ls和%s的意义在于指明的参数是何种字符串,而printf和wprintf的区别在于所使用的是不同类型的stream,不要混用 char 和 wchar_t 版本的流操作函数,否则会导致这些函数运行异常)

putwchar

putwchar函数专门用来输出一个宽字符,它和 putchar 的用法类似

wchar_t ch = L‘Z‘;
putwchar(ch);

运行结果:

原文地址:https://www.cnblogs.com/lanhaicode/p/10574260.html

时间: 2024-11-10 12:05:46

宽字符wchar_t和窄字符char——putwchar、wprintf的相关文章

宽字符和窄字符之间的转换,以及对中文的处理问题总汇

直接代码: 注:编译环境VS2010 SP1 1 /*实现宽字节和窄字符转换以及中文文件的输入输出*/ 2 3 #include <iostream> 4 #include <string> 5 #include <fstream> 6 #include <locale> 7 #include <codecvt> 8 #include <windows.h> 9 #include <tchar.h> 10 using na

volatile,可变参数,memset,内联函数,宽字符窄字符,国际化,条件编译,预处理命令,define中##和#的区别,文件缓冲,位域

 1.volatile:要求参数修改每次都从内存中的读取.这种情况要比普通运行的变量需要的时间长. #include <stdio.h> #include <stdlib.h> #include <time.h> void main() { time_t start, end; double res = 0; time(&start);  //获取时间,传递给start //volatile强制每次从内存读取 volatile int i; for (i =

控制台输出宽字符wchar_t的中文显示问题

在缺省的C locale下,cout可以直接输出中文,但对于wcout却不行(至少VS 2005下不行).对于wcout,需要将其locale设为本地语言才能输出中文: wcout输出时显示不了中文,加上下面这句就行了. std::wcout.imbue(std::locale("chs")); ----------------------------------------------------------------------------- #include <iostr

tableview中index对英文字符汉字字符(窄字符宽字符)处理

[问题描述] 开发iOS通讯录项目,遇到一个tableview 索引的问题. 测试同学发现一个bug:添加一个名字为宽字符A不能归并到索引A的section中,而是使用了添加了一个叫A的索引,如图: 上图中:右侧索引尾部发生异常.ABX并没有归并到正常的索引中,而是出现在正常索引的Z和#之间了. [问题分析] 想了一下,应该是宽字符A和A的编码不一致导致的. 之前代码是这样的,看第二行使用正则表达式判断首字母是不是拉丁字母开头,然后标注此人是以某个字符开头的,代码如下: NSPredicate*

编译问题提示包含窄字符的问题

查看本工程和包含的文件,Character set已经全部设为Use Unicode Character Set: 编译总是失败提示 包含了窄字符: 最后改了地方解决,上图: 勾选红色圈住的地方: 显示会多出来如下图: 或者将%(AdditionalDependencies) 复制到input库的后面,也可以,相同的效果.

C语言字符型数据(字符)

字符型数据的表示 字符型数据就是字符. 字符型数据是用单引号括起来的一个字符.例如: 'a'.'b'.'='.'+'.'?' 都是合法字符型数据. 在C语言中,字符型数据有以下特点: 字符型数据只能用单引号括起来,不能用双引号或其它括号. 字符型数据只能是单个字符,不能是字符串. 字符可以是字符集中任意字符.但数字被定义为字符型之后就不能参与数值运算.如'5'和5 是不同的.'5'是字符型数据,不能参与运算. 转义字符 转义字符是一种特殊的字符.转义字符以反斜线"\"开头,后跟一个或几

java小练习:输入一个字符,判断该字符是数字?英文字母?还是其他字符

package practiceGO; import java.util.Scanner; /*  * 3.输入一个字符,判断该字符是数字?英文字母?还是其他字符  */ public class Cto { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("输入一个字符:"); char ch = sc.next().charAt(0);

从字符数组中删除字符

/*实现程序的功能:从字符数组s中删除存放在c中的字符.*/ #include <stdio.h> int main(int argc, const char *argv[]) { char s[80],c; printf("请输入一个字符串\n"); gets(s); printf("请输入一个字符\n"); scanf("%c",&c); //遍历字符串 for (int i = 0; s[i] != '\0'; i++)

Unicode其实是Latin1的扩展。只有一个低字节的Uncode字符其实就是Latin1字符——附各种字符编码表及转换表

一.概念 1,ASCII ASCII(American Standard Code for Information Interchange),中文名称为美国信息交换标准代码.是基于拉丁字母的一套电脑编码系统.它主要用于显示现代英语和其他西欧语言.它是现今最通用的单字节编码系统.ASCII码又分为标准ASCII码和扩展ASCII码. 标准ASCII码.标准ASCII 码也叫基础ASCII码,使用7 位二进制数来表示所有的大写和小写字母,数字0 到9.标点符号, 以及在美式英语中使用的特殊控制字符.