`
wangangie12
  • 浏览: 45537 次
  • 性别: Icon_minigender_2
  • 来自: 厦门
最近访客 更多访客>>
社区版块
存档分类
最新评论

windows编程中字符和字符串的处理

阅读更多

  字符格式基础
  首先说说字符编码的两种格式。
  一种是将文本字符串编码成一组以0结尾的单字节字符,即ansi字符,每个字符占8位,即一个字节。这种编码方式的缺陷是,对于字符本地化的问题不能很好的解决,因为8位空间最多容纳256个字符,不能完全唯一的表示世界上所有的字符。
  另一种是Unicode字符,每个字符都使用UTF-16编码(一般来说,除非特别声明不使用UTF-16编码),即一个字符占16位空间(2字节)。基于这种情况,世界上大多数语言的字符都可以用一个唯一的2字节空间表示。
  传统的ansi字符在C语言中用char数据类型表示(1字节)。在源代码中声明一个字符串,则编译器会转换为由8位char数据类型构成的一个数组(以"/0"结尾)
  char c='a';//一个8位的字符
  char szbuffer[100]="a string";//含有99个8位字符和1个8位结束符(/0)的数组
  微软的c/c++编译器为unicode定义了一个内建的数据结构,wchar_t,它表示一个16位的unicode(UTF-16)字符。
  wchar_t c=L'a';//一个16位的字符
  wchar_t szbuffer[100]=L"a string";//含有99个16位字符和1个16位结束符(/0)的数组
  此外,windows为了和c语言加以区别,则定义了自己的数据类型。
  //WinNT.h
  typedef char CHAR;//一个8位的字符
  typedef wchar_t WCHAR;//一个16位的字符
  typedef CHAR *PCHAR;//指向8位字符的指针
  typedef CHAR *PSTR;//指向8位字符的指针
  typedef CONST CHAR *PCSTR;//指向8位字符的常量指针
  typedef WCHAR *PWCHAR;//指向16位字符的指针
  typedef WCHAR *PWSTR;//指向16位字符的指针
  typedef CONST WCHAR *PCWSTR;//指向16位字符的常量指针
  在实际使用中,使用哪种类型并不重要,但最好保持一致,这样有利于维护。另外如果是windows编程,最好使用windows定义的数据类型,这样可与MSDN保持一致,有利于开发。
  windows还定义了如下宏和通用数据类型,来方便开发人员。
  #ifdef UNICODE
  typedef WCHAR TCHAR ,*PTCHAR,PTSTR;
  typedef CONST WCHAR *PCTSTR;
  #define __TEXT(quote) quote
  #define __TEXT(quote) L##quote
  #else
  typedef CHAR TCHAR ,*PTCHAR,PTSTR;
  typedef CONST CHAR *PCTSTR;
  #define __TEXT(quote) quote
  #endif
  #define __TEXT(quote) L##quote
  其中黑体部分的类型都是通用数据类型,即无论使用ansi还是unicode,都能通过编译。
  TCHAR c=TEXT('A');//如果定义了unicode,则a是16位字符;如果定义了ansi,则a是8位字符
  TCHAR SZBUFFER[100]=TEXT("A STRING");//如果定义了unicode,则SZBUFFER中的字符为16位;否则,字符位8位。
  自windowsNT开始,windows所有版本都使用unicode构建。即如果我们的程序使用ansi字符,那么操作系统将会执行转换为unicode,这些转换都是对用户透明的,且会产生时间和内存的开销。所以,我们应尽量使用unicode构建程序。
  至此为止,总结一下,就是定义字符用TCHAR,指针类型使用*TCHAR足以,定义字面值用_T宏。
  windows中的函数的参数列表中如果有字符串,则该函数通常有两个版本,一个ansi,一个unicode。例如CreateWindowEx接受这两种类型的字符串作为参数。实际上,CreateWindowEx只是一个宏,定义如下:
  //WinUser.h
  #ifdef UNICODE
  #define CreateWindowEx  CreateWindowExW
  #else
  #define CreateWindowEx  CreateWindowExA
  #endif
  很明显,这和前面的通用数据类型使用的是同一伎俩。其中CreateWindowExW接受Unicode,CreateWindowExA接受ansi。
  在windows vista中,CreateWindowExA只是一个转换层,负责分配内存,然后将ansi转换为unicode,然后在内部调用CreateWindowExW。
  C运行库中的安全字符串处理函数
  通常,修改字符串的函数都存在一个安全隐患,即目标字符串的缓冲不够大,则会导致内存中的数据被破坏。
  例如:
  WCHAR szbuffer[3]=L"";
  wcscpy(szbuffer,L"abc");
  以上的例子是以0结尾的,需要szbuffer[4]才可以容纳。但编译时并不会有任何报错或警告。
  针对以上问题,我们必须使用"安全字符串处理函数",这一类的函数以_s结尾(secure之意),我们来看一下这类函数的原型.
  PTSTR _tcscpy(PTSTR strDestination,PCTSTR strSource);
  errno_t _tcscpy_s(PTSTR strDestination,size_t numberOfCharacters,PCTSTR strSource);
  PTSTR _tcscat(PTSTR strDestination,PCTSTR strSource);
  errno_t  _tcscat_s(PTSTR strDestination,size_t numberOfCharacters,PCTSTR strSource);
  可以看到,在将一个缓冲区作为目标缓冲区时,必须提供这个缓冲区的大小(可容纳的字符个数),通过调用_countof宏计算出来。
  这个缓冲区大小参数的主要任务就是验证缓冲区是否足以容纳结果数据.
  现在,我们调用这些安全函数的时候,就可以检查返回的errno_t值。只有返回S_OK值,才表明函数调用成功。其他的值可以参照errno.h中的定义。
  来看一个例子:
  TCHAR szbuffer[3]=L"";
  _tcscpy_s(szbuffer,_countof(szbuffer),_T("abc"));
  执行完后, szbuffer的第一个字符被设置为'\0',而其他所有字节全部被设置为0xfd(填充符)。 在处理字符串时获得更多的控制
  除了安全字符串处理函数,c运行库还增加了一些函数,用于在处理字符串时获得更多的控制。例如,可以控制如何截断字符串。
  这类函数具有两个版本,对应ansi和unicode。
  HRESULT StringCchCat( LPTSTR pszDest,size_t cchDest,LPCTSTR pszSrc);
  HRESULT StringCchCatEx( LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc,LPTSTR *ppszDestEnd,size_t *pcchRemaining,DWORD dwFlags);
  HRESULT StringCchCopy( LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc);
  HRESULT StringCchCopyEx(LPTSTR pszDest,size_t cchDest, LPCTSTR pszSrc, LPTSTR *ppszDestEnd,size_t *pcchRemaining,DWORD dwFlags);
  可以看出,在所有方法的名称中,都含有一个"Cch",这表示count of characters,即字符个数。通常使用_countof宏获得。
  另外还有一些函数含有"cb",这表示函数要求用字节数来指定大小。通常使用sizeof()获得。
  这些函数返回HRESULT,具体的值
  S_OK 成功。目标缓冲区中包含源字符串,并以/0终止 
  STRSAFE_E_INVALID_PARAMETER 失败。将NULL传给了一个参数 
  STRSAFE_E_INSUFFICIENT_BUFFER 失败。指定的目标缓冲区太小,无法容纳整个源字符串 
  不同于安全字符串处理函数,这类函数运行时,当缓冲区太小,则会执行截断。
  windows字符串处理函数
  在shlwapi.h定义了大量好用的字符串函数,可以用来对操作系统有关的数值进行格式化操作。
  在实际编程中,经常需要比较两个字符串是否相等。对于这样的需求可以使用CompareString(Ex)或者CompareStringOrdinal。
  CompareString(Ex)一般用于向用户显示的字符串。
  CompareStringOrdinal一般用于比较程序内部的字符串,如路径名,注册表项值等。
  CompareString(Ex)的处理速度相对于CompareStringOrdinal较慢。
  这两个函数的返回0,则表示调用失败;
  返回1(CSTR_LESS_THAN)表明string1小于string2;
  返回2(CSTR_GREATER_THAN)表明string1大于string2.
  使用unicode的好处:
  1、有利于应用程序的本地化。
  2、代码执行效率更高,因为windows基于unicode构建,如果我们也保持一致,则windows处理时不必耗费额外的资源转换。
  3、容易与com集成
  4、容易与.net集成
  推荐的字符处理方式
  1、使用通用数据类型和宏,如TCHAR和_T
  2、将字符串想象成字符的数组,而非char或字节的数组。
  3、与字符串有关的计算需修改。尤其要搞清楚很多的函数要求传递的是字符数还是字节数,如是前者,则用_countof()获取;如是后者,则用(字符数*sizeof(字符类型))获取。
  4、避免使用printf系列函数转换ansi和unicode。正确的做法是使用MultiByteToWideChar或WideCharToMultiByte。
  5、始终使用安全的字符串处理函数,_s或stringcch,如要控制截断,则使用后者。
  6、如果一个缓冲区处理函数的参数中不包括目标缓冲区的长度,那么避免使用。
  7、比较字符串时,使用CompareStringOrdina和CompareString(Ex)。前者速度快,适合处理程序内部的字符串;后者用于处理UI的字符串,因为它是以区域设置来适当排序,速度较慢。
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/shentao17792/archive/2010/02/ 21/5314312.aspx
分享到:
评论

相关推荐

    windows编程 会移动的字符串

    设计规则:假设有一个字符串为“ABCDE”, 每按下一次任意键(响应WM_KEYDOWN消息),该字符串就往前移动一格,当字符串的第一个字符碰到窗口的用户区域的边界时,该字符串就反方向移动。字符串每移动一格,颜色将随机...

    Windows编程 移动的字符串

    上下左右键可控制文字移动 回车键文字沿45度角移动,遇边界反弹

    Windows驱动编程视频教程-内核模式下的字符串操作

    Windows驱动编程视频教程 详尽的讲解 里面还有屏幕录制的录像

    windows字符串的前世今生

    CString、LPCTSTR、LPTSTR、TCHAR、WCHAR、string、wchar_t、char各种类型的转发与字符集的发展演变,通过思维导图清晰表示他们之间的关系,让初学者摆脱windows编程,常常遇到的的字符集的困惑。

    bash过滤字符串的命令介绍

    该文档介绍了shell编程中对字符串处理的一些基本命令, 如sed, cut, awk等等

    Windows核心编程.zip

    Windows核心编程.zip dll 进程 内存体系结构 栈\堆 内存映射文件 线程 字符和字符串处理

    Windows编程基础--窗体篇.rar_WinMain_Windows编程_pcm_winapi_winbase.h

    Windows编程基础--窗体篇  现在Windows已经成为世界上使用最广泛的操作系统,这使得学习Windows编程变得十分重要.和学习其他 编程语言一样,我们也从一个最简单的例子开始学习Windows编程.这个例子将建立一个...

    C#使用tcp协议socket收发字符串文本数据,比如json字符串,xml字符串或者是纯文本数据

    该程序用C#编写,基于第三方类库实现TCP协议收发文本数据,比如Json,...SharpSocket底层采用Windows的IOCP模型,是最稳定和高效的Socket编程模型。SharpSocket代码经过精心优化, 有些直接在IL层编写,处理数据更快速!

    Windows驱动编程基础教程.pdf

    第一章 字符串 6 1.1 使用字符串结构 6 1.2 字符串的初始化 7 1.3 字符串的拷贝 8 1.4 字符串的连接 8 1.5 字符串的打印 9 第二章 内存与链表 11 2.1内存的分配与释放 11 2.2 使用LIST_ENTRY 12 2.3 使用长长整型...

    windows API编程基础 02

    windows doc 关于windowsAPI编程的一些知识...

    天书夜读:从汇编语言到Windows内核编程(完整版一)

     第2章 C语言的流程和处理 14  2.1 C语言的循环反汇编 15  2.1.1 for循环 15  2.1.2 do循环 16  2.1.3 while循环 17  2.2 C语言判断与分支的反汇编 18  2.2.1 if-else判断分支 18  2.2.2 switch-case判断...

    天书夜读:从汇编语言到Windows内核编程(完整版 二)

     第2章 C语言的流程和处理 14  2.1 C语言的循环反汇编 15  2.1.1 for循环 15  2.1.2 do循环 16  2.1.3 while循环 17  2.2 C语言判断与分支的反汇编 18  2.2.1 if-else判断分支 18  2.2.2 switch-case判断...

    C# Windows编程基础

    案例1:循环语言的学习-砝码程序验证 案例2:...--消去字符串空格 案例7:委托的使用方法实例---加减大小比较 案例8:用C#索引器实现文本文件的倒叙输入 案例9:C#文本文件操作实例---杨辉三角形写入读出

    Visual C++ 2005入门经典--源代码及课后练习答案

    6.7.2 从字符串中删除空格 268 6.7.3 计算表达式的值 268 6.7.4 获得项值 271 6.7.5 分析数 272 6.7.6 整合程序 274 6.7.7 扩展程序 276 6.7.8 提取子字符串 277 6.7.9 运行修改过的程序 280 6.8 ...

    精通Windows.API-函数、接口、编程实例.pdf

    15.2.5 字符串表 469 15.3 安装程序setup.exe的编号 469 15.4 使用msi文件进行安装 472 15.4.1 Windows Installer Service 472 15.4.2 msi文件的创建与修改工具orca.exe 474 15.4.3 准备工作 475 15.4.4...

    windows内核编程

    windows内核下操作字符串

    精通WindowsAPI 函数 接口 编程实例

    15.2.5 字符串表 469 15.3 安装程序setup.exe的编号 469 15.4 使用msi文件进行安装 472 15.4.1 Windows Installer Service 472 15.4.2 msi文件的创建与修改工具orca.exe 474 15.4.3 准备工作 475 15.4.4...

    Windows编程技术

    3.2.5 字符串处理函数 39 3.3 集合类 39 3.3.1 列表类CList 40 3.3.2 数组类CArray 43 3.3.3 映射类CMap 45 3.4 时间处理类 47 3.4.1 COleDateTime类 47 3.4.2 COleDateTimeSpan类 51 3.5 异常处理类 52 3.5.1 异常...

    获取APP.Config连接字符串.rar

    获取APP.Config连接字符串.rar windows 编程

Global site tag (gtag.js) - Google Analytics