浅谈Windows的各种“字符串”

这篇具有很好参考价值的文章主要介绍了浅谈Windows的各种“字符串”。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

绪论:中文用几个字节保存

不知道你们的大学老师有没有说过中文是用两个字节保存,直到我了解了字符编码,然后留下了这几行代码

#include<string.h>
#include<stdio.h>
int main()
{
	wchar_t w = 'a';	 //宽字节
	char c = 'a';		 // 多字节

	char *pc;
	wchar_t *pw;

	pc = "abc中";		//多字节字符串的赋值
	pw = L"abc中";		//宽字节字符串的赋值

	int clen = strlen(pc);	//求多字节字符串的长度   	clen=5
	int wlen = wcslen(pw);	//求宽字节字符串的长度	wlen=4;
	printf("strlen:%d,wcslen:%d\n", clen, wlen);
	return0;
}
strlen:5,wcslen:4

结果很明显,不同的编码方式,中文所占字节也不一样 ,而这就要从Windows下的字符集说起。

说起Windows下的编程,可能大家的印象都是:微软从来都“特立独行”,什么都要来自己的一套,连类型都不例外。C语言下预设的一些基本类型,微软几乎都typedef过,如BYTE,WORD,DWORD等。那么,今天我们来简单聊聊Windows编程下的字符集和字符串类型。

之所以要聊一聊这个,是因为在过年前有一个同学来我们公司面试,我们让面试的同学写一段代码,其中有一个功能是输出一段文字,结果输出内容始终都不对。那么现在开始简单的梳理一下,Windows下常见的这些字符串类型。

一、ASCII和UNICODE

在很久很久以前,天地一片混沌之时,操作系统大部分都是英文系统。当时的人们认为,我们只要用很少的二进制位数,就可以表示大部分我们需要的字符,这也就是ASCII编码规范。然鹅,现实总是很骨感,很快人们发现,短短七八位的二进制位数根本不能满足全宇宙人民的需要,于是UNICODE应运而生,它致力于整理一套统一的规范来表示所有我们用到的字符。我们可以认为UNICODE是兼容ASCII的,只是它会占用更多的空间。每一个字符对应一个UNICODE编码,至于编码如何布局(布局是指每个二进制位的含义),我们又规定了诸多编码规范,其中最为出名的就是utf-8utf-16

如果不考虑国际化,统一用ascii,那么每个字符将占用8位,也就是一个字节的大小。如果用utf-16来表示字符串,那么每个字符至少是16位,也就是2个字节。这也就决定了,字节的基本长度到底是一个字节,还是两个字节。

在Windows中,内部是以utf-16来保存字符串的。它支持两套API,用来兼容ASCII和UNICODE,分别以A和W结尾。例如,MessageBoxA表示它接受ASCII类型的字符串,而MessageBoxW表示接受UNICODE字符串

在代码中,若是定义UNICODE和_UNICODE,则Windows API将会展开为带W的函数,否则将展开为带A的函数。例如,定义了UNICODE的情况下,MessageBox会被展开为MessageBoxW

二、char和wchar_t

同时支持ASCII和UNICODE,这给C程序员带来了无尽的麻烦。这不得不定义一种新类型来表示UNICODE,这便是wchar_t。char众所周知,表示的是一个字符,如'a', '1'都是char。wchar_t表示的是一个“宽字符”,它的长度比char要大,在vs下为16位,和short一致。在定义一个宽字符组成的字符串时,要在字面值前加上L,如L'a',表示的就是一个宽字符a。

C语言中的字符串,其实就是以0结尾的一串字符。而字符又分为窄字符(char)和宽字符(wchar_t)。同样的,在字符串字面值前加上L表示的是宽字符串,如L"hello"

我们在对字符串进行操作时,必须要小心翼翼,了解它到底是宽字符串还是窄字符串。例如,在获取字符串长度时,窄字符串是strlen,而宽字符串是wcslen。我一直都搞不懂为什么不按照strlen的命名规则来,命名为wstrlen呢,这样多容易记。好在两个函数明确写出了一个接受的参数是const char*,另外一个是const wchar_t*,如果传入了错误的字符串类型,则会得到一个错误。不幸的是,有些函数可能接受的是一个void*,如果你传入了错误的字符串类型,则可能要花大把时间来定位问题。

三、LPCSTR和LPCWSTR

这两个是Windows API中最为常见的两种字符串类型。LP表示Long Pointer,指针。C表示const,STR表示窄字符串,WSTR表示宽字符串,那么翻译过来就是:

LPCSTR = constchar*

LPCWSTR = constwchar_t*

很多初学者在定义了UNICODE的情况下,调用一些API,却传入了LPCSTR,这样就会得到一个编译错误。解决的方式就是在字面值前加上L。

四、TCHAR,LPCTSTR

如果我们希望编写编码集无关的代码,我们很可能会写出以下代码:

#ifndef _UNICODE
LPCSTR szStr = "hello";
#else
LPCWSTR szStr = L"hello";
#endif

有没有办法来自动区分是否是用ASCII还是UNICODE?微软提供了TCHAR,以及TCHAR字符串类型LPCTSTR

简单来说,TCHAR和LPCTSTR会根据当前字符集来选择字符类型。使用_T宏将字符串包围起来,如_T("hello"),如果是UNICODE字符集,将会被展开为L"hello",否则不变。

那么以上代码可以改为:

  LPCTSTR szStr = _T("hello");

五、更多类型,如OLECHAR,BSTR,CString,QString

OLECHAR和BSTR用于COM编程,它们都有相应的函数来创建、控制和销毁。CString是ATL中封装的一个字符串类型,多用于MFC项目。QString是Qt中强大的字符串类。

六、建议

之前提到有一个同学来面试,他使用了LPCTSTR来保存一个字符串,然后用std::cout来输出字符串,结果只得到了一个指针的地址。原来他在vs设置里,将字符集调成了UNICODE,那么其实他定义的是个宽字符串,得有wcout才能得到正确的结果。

以下是建议:

1.尽量使用UNICODE字符集。它对程序效率有提升(因为Windows是用utf-16保存字符串),不会在底层进行字符集的转换。

2.尽量使用同一体系下的字符串。例如,如果是C风格的Windows编程,那么就尽量不要std和Windows风格字符串混用。可以参考Windows核心编程,里面介绍了如何用Windows API来操控字符串。同样,也尽量不要混用LCPSTR,CString以及QString等,除非你知道中间到底发生了什么。

如果有可能的话,可以看看Qt中QString的源代码,使用它几乎可以满足所有字符串的要求。

最后说一下,字符串看似简单,其实里面蕴藏的知识不少,希望大家阅读了本文之后,能对字符串类型有个基本的了解。文章来源地址https://www.toymoban.com/news/detail-499550.html

到了这里,关于浅谈Windows的各种“字符串”的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 浅谈Golang等多种语言转数组成字符串

    目录 Python 一维列表转字符串 二维列表转字符串 多维列表转字符串 Golang 一维数组的遍历打印 二维数组的遍历打印  Java 一维容器的直接打印 二维容器的直接打印 普通数组的转化 C++ 一维容器的遍历 1. to_string() 2. stringstream 二维容器的遍历 简要小结 python语言中没有普通的数

    2024年02月03日
    浏览(32)
  • 浅谈字符串的定义(c++)非常详细,建议收藏

    C++ 有一个新的数据类型——字符串类型。这里的 string 是 C++ 所独有的,C语言没有。 定义一个值为 Initial string 的字符串 s s s ,包括空格。 定义一个空字符串 s s s 。 定义一个 s 0 s0 s 0 字符串的copy字符串 s s s 。 定义一个字符串 s 3 s3 s 3 ,该字符串的值为从 s 0 s0 s 0 的第 8

    2024年02月08日
    浏览(42)
  • JAVA 十六进制与字符串的转换浅谈

      笔者前几日在开服过程中需要将字符串转化成为16进制的字符串,在网上找到了一些方法尝试之后,均发现存在一个问题--字符串转为16进制后再转回来,英文正常,中文出现乱码 笔者前几日在开服过程中需要将字符串转化成为16进制的字符串,在网上找到了一些方法尝试之后,均发

    2024年02月07日
    浏览(35)
  • Java 字符串截取方法大全,助你轻松应对各种场景

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 在 Java 开发中,经常会涉及到对字符串进行截取操作。字符串截取是一种常见且重要的字符串处理技巧,可以根据

    2024年02月16日
    浏览(33)
  • (python)正则表达式提取字符串中的各种信息(持续更新)

            在日常数据处理过程,拿到一段文字,进行关键信息的提取.总而言之,翻来覆去地用到几种处理方法.这些都需要用到正则去进行通用处理.比如提取关键信息,诸如时间,日期,地址等. 那么我们要根据关键信息的特征去提取. 数字提取:可以用正则表达式来提取数字,包括整

    2024年01月24日
    浏览(39)
  • JS两种方法判断字符串是否包含中文

    第一种是正则表达式来判断,判断输入的字符中是否包含中文。 第二种是通过charCodeAt()来判断,字符串.charCodeAt(index)255 就是中文,否则是英文。

    2024年02月13日
    浏览(53)
  • 解决Java中文乱码问题:使用System.out.println输出中文字符串

    解决Java中文乱码问题:使用System.out.println输出中文字符串 在Java编程中,当我们想要在控制台输出中文字符串时,有时会遇到乱码的问题。本文将介绍如何解决这个问题,并提供相应的源代码示例。 在Java中,我们通常使用System.out.println语句来在控制台输出字符串。然而,当

    2024年02月06日
    浏览(30)
  • 中文编程入门(Lua5.4.6中文版)第七章 Lua 字符串与模式

    在网游的符文之地中,我们可以通过神秘的“字符串法术”来处理和操作一系列字符。以下是如何在Lua的魔法卷轴上施展这种法术: 字符串的表示与召唤:  在Lua的魔法治则中,你可以运用三种方式召唤出一串字符(即字符串): 单引号(\\\')内的字符序列。 双引号(\\\")内的字符

    2024年03月19日
    浏览(29)
  • 如何去掉字符串中文括号及其内部的内容两种方式

    第一种:使用正则表达式。问题是可以直接把英文括号及里面的内容删除,但是对中文括号处理不了。只好先替换为英文括号,然后再全局替换。 它的优点很显然:能处理中文双括号,英文双括号,前面是英文括号后面是中文括号,前面是中文括号后面是英文括号的各种情况

    2024年02月20日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包