- 浏览: 642100 次
- 性别:
- 来自: 武汉
文章分类
最新评论
-
lizhuang:
这个方法的内部实现主要是依赖于类加载器,一般的自己实现的类是用 ...
Java中getResourceAsStream的用法 -
prince4426:
回答评论都很精彩
Java中getResourceAsStream的用法 -
kexuetou:
美人如此多娇 写道可能这样总结更好,路径前不带'/',则是相对 ...
Java中getResourceAsStream的用法 -
guoxin91:
...
Java中getResourceAsStream的用法 -
美人如此多娇:
可能这样总结更好,路径前不带'/',则是相对路径;若带,则是绝 ...
Java中getResourceAsStream的用法
引言
wchar_t wch = L''1''; // 2 bytes, 0x0031 wchar_t* wsz = L"Hello"; // 12 bytes, 6 wide characters
字符在内存中是怎样存储的
Unicode的存储形式,L"Bob"
使用两个字节表示的0来做结束标志。
值得注意的是,"ni"的值不能被解释成WORD型值0xfa93,而应该看作两个值93和fa以这种顺序被作为"ni"的编码。 使用字符串处理函数
因为x86 CPU是little-endian,值0x0042在内存中的存储形式是42 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是strlen()将会返回1。如果把"Bob"传给wcslen(),将会得出更坏的结果。wcslen()将会先看到0x6f42,然后是0x0062,然后一直读到你的缓冲区的末尾,直到发现00 00结束标志或者引起了GPF。 正确的遍历和索引字符串 我们先来阐述规则2,因为找到一个违背它的真实的实例代码是很容易的。假设你有一个程序在你自己的目录里保存了一个设置文件,你把安装目录保存在注册表中。在运行时,你从注册表中读取安装目录,然后合成配置文件名,接着读取该文件。假设,你的安装目录是C:\Program Files\MyCoolApp,那么你合成的文件名应该是C:\Program Files\MyCoolApp\config.bin。当你进行测试时,你发现程序运行正常。 bool GetConfigFileName ( char* pszName, size_t nBuffSize ) { char szConfigFilename[MAX_PATH]; // Read install dir from registry... we''ll assume it succeeds. // Add on a backslash if it wasn''t present in the registry value. // First, get a pointer to the terminating zero. char* pLastChar = strchr ( szConfigFilename, ''\0'' ); // Now move it back one character. pLastChar--; if ( *pLastChar != ''\\'' ) strcat ( szConfigFilename, "\\" ); // Add on the name of the config file. strcat ( szConfigFilename, "config.bin" ); // If the caller''s buffer is big enough, return the filename. if ( strlen ( szConfigFilename ) >= nBuffSize ) return false; else { strcpy ( pszName, szConfigFilename ); return true; } }这是一段很健壮的代码,然而在遇到 DBCS 字符时它将会出错。让我们来看看为什么。假设一个日本用户使用了你的程序,把它安装在 C:\。下面是这个名字在内存中的存储形式:
当使用 GetConfigFileName() 检查尾部的''\\''时,它寻找安装目录名中最后的非0字节,看它是等于''\\''的,所以没有重新增加一个''\\''。结果是代码返回了错误的文件名。 bool FixedGetConfigFileName ( char* pszName, size_t nBuffSize )
{
char szConfigFilename[MAX_PATH];
// Read install dir from registry... we''ll assume it succeeds.
// Add on a backslash if it wasn''t present in the registry value.
// First, get a pointer to the terminating zero.
char* pLastChar = _mbschr ( szConfigFilename, ''\0'' );
// Now move it back one double-byte character.
pLastChar = CharPrev ( szConfigFilename, pLastChar );
if ( *pLastChar != ''\\'' )
_mbscat ( szConfigFilename, "\\" );
// Add on the name of the config file.
_mbscat ( szConfigFilename, "config.bin" );
// If the caller''s buffer is big enough, return the filename.
if ( _mbslen ( szInstallDir ) >= nBuffSize )
return false;
else
{
_mbscpy ( pszName, szConfigFilename );
return true;
}
}
上面的函数使用CharPrev() API使pLastChar向后移动一个字符,这个字符可能是两个字节长。在这个版本里,if条件正常工作,因为lead byte永远不会等于0x5c。
2a. 永远不要使用减法去得到一个字符串的索引。 违背这条规则的代码和违背规则2的代码很相似。例如, char* pLastChar = &szConfigFilename [strlen(szConfigFilename) - 1]; 这和向后移动一个指针是同样的效果。 回到关于str***()和_mbs***()的区别 Win32 API中的MBCS和Unicode BOOL WINAPI SetWindowTextA ( HWND hWnd, LPCSTR lpString ); BOOL WINAPI SetWindowTextW ( HWND hWnd, LPCWSTR lpString ); #ifdef UNICODE #define SetWindowText SetWindowTextW #else #define SetWindowText SetWindowTextA #endif当使用MBCS APIs来build程序时,UNICODE没有被定义,所以预处理器看到: #define SetWindowText SetWindowTextA 这个宏定义把所有对SetWindowText的调用都转换成真正的API函数SetWindowTextA。(当然,你可以直接调用SetWindowTextA() 或者 SetWindowTextW(),虽然你不必那么做。) HWND hwnd = GetSomeWindowHandle(); char szNewText[] = "we love Bob!"; SetWindowText ( hwnd, szNewText ); 在预处理器把SetWindowText用SetWindowTextW来替换后,代码变成: HWND hwnd = GetSomeWindowHandle(); char szNewText[] = "we love Bob!"; SetWindowTextW ( hwnd, szNewText ); 看到问题了吗?我们把单字节字符串传给了一个以Unicode字符串做参数的函数。解决这个问题的第一个方案是使用 #ifdef 来包含字符串变量的定义: HWND hwnd = GetSomeWindowHandle(); #ifdef UNICODE wchar_t szNewText[] = L"we love Bob!"; #else char szNewText[] = "we love Bob!"; #endif SetWindowText ( hwnd, szNewText ); 你可能已经感受到了这样做将会使你多么的头疼。完美的解决方案是使用TCHAR. 使用TCHAR #ifdef UNICODE typedef wchar_t TCHAR; #else typedef char TCHAR; #endif 所以用MBCS来build时,TCHAR是char,使用UNICODE时,TCHAR是wchar_t。还有一个宏来处理定义Unicode字符串常量时所需的L前缀。 #ifdef UNICODE #define _T(x) L##x #else #define _T(x) x #endif ##是一个预处理操作符,它可以把两个参数连在一起。如果你的代码中需要字符串常量,在它前面加上_T宏。如果你使用Unicode来build,它会在字符串常量前加上L前缀。 TCHAR szNewText[] = _T("we love Bob!"); 像是用宏来隐藏SetWindowTextA/W的细节一样,还有很多可以供你使用的宏来实现str***()和_mbs***()等字符串函数。例如,你可以使用_tcsrchr宏来替换strrchr()、_mbsrchr()和wcsrchr()。_tcsrchr根据你预定义的宏是_MBCS还是UNICODE来扩展成正确的函数,就像SetWindowText所作的一样。 字符串和TCHAR typedefs
何时使用 TCHAR 和 Unicode Windows 9x 中大多数的 API 没有实现 Unicode 版本。所以,如果你的程序要在windows 9x中运行,你必须使用MBCS APIs。然而,由于NT系统内部都使用Unicode,所以使用Unicode APIs将会加快你的程序的运行速度。每次,你传递一个字符串调用MBCS API,操作系统会把这个字符串转换成Unicode字符串,然后调用对应的Unicode API。如果一个字符串被返回,操作系统还要把它转变回去。尽管这个转换过程被高度优化了,但它对速度造成的损失是无法避免的。
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
作者简介 |
发表评论
-
main中调用dll中的函数,F10单步到main的右大口号时出现user breakpoint called...
2010-03-09 18:42 1784在dll中输出了一个包含string类子对象的类,在DEBUG ... -
VC中链接动态链接库的方法
2010-03-06 17:17 1379方法一:windows提供了一套函数,用于加载动态链接库中的符 ... -
50个C/C++源代码网站
2010-01-30 13:01 3020C/C++是最主要的编程语言。这里列出了50名优秀网站和网页清 ... -
《Effective C++》条款34: 将文件间的编译依赖性降至最低
2010-01-29 21:04 2162假设某一天你打开自己的C++程序代码,然后对某个类的实现做了小 ... -
QHttp
2010-01-26 17:06 7032QHttp是Qt所提供有关网络的高阶API,可以协助我们进行H ... -
VC屏蔽Enter和ESC退出程序
2010-01-15 21:51 2437重载PreTranslateMessage函数屏蔽回车和ESC ... -
《Effective C++》条款22:尽量用"传引用"代替"传值"
2010-01-13 11:15 2912c语言中,什么都是通过传值来实现的,c++继承了这一传统并将它 ... -
《高质量C++/C 编程指南》之 内存耗尽怎么办
2010-01-12 14:20 1617如果在申请动态内存时找不到足够大的内存块,malloc ... -
《高质量C++/C 编程指南》之 常见的内存错误及其对策
2010-01-12 14:10 1470发生内存错误是件非 ... -
《高质量C++/C 编程指南》之 有了malloc/free为什么还要new/delete
2010-01-12 13:33 1732malloc与free是C++/C语言的标准库函 ... -
《高质量C++/C 编程指南》之 free和delete把指针怎么啦?
2010-01-12 11:30 1288别看free和delete的名字恶狠狠的(尤其是delete) ... -
《高质量C++/C 编程指南》之 杜绝"野指针"
2010-01-12 11:27 1307“野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般 ... -
《Effective C++》条款14: 确定基类有虚析构函数
2010-01-12 11:18 5178有时,一个类想跟踪它 ... -
数组名不完全等于指针
2010-01-10 19:12 1829指针是C/C++语言的特色,而数组名与指针有太多的相似,甚至很 ... -
C++字符串完全指引之二
2010-01-09 16:16 1538引言 因为C语言 ... -
BMP文件格式
2010-01-08 22:15 1869一.位图结构如下: ---- 一、BMP文件结构 --- ... -
OpenCV基础数据结构
2010-01-08 21:56 2175图像数据结构: 1) IPL ... -
OpenCV基本知识
2010-01-08 21:31 29881、OpenCV概述 1) 什么是OpenCV 开 ... -
calloc(), malloc(), realloc(), free()
2010-01-08 21:08 1432void *calloc(size_t nobj, size_ ... -
善用GetLastError函数
2010-01-08 21:06 2215在编程过程中,当程序出现错误,却又不知道错误的原因 ...
相关推荐
C++字符串完全指引之一 Win32 字符编码 C++字符串完全指引之二 字符串封装类 详细介绍了c++字符编码和字符串相关类
### C++字符串完全指引:深度解析与转换技巧 在C++编程中,字符串处理是一项基本且重要的技能。本文旨在提供一份全面的C++字符串指南,深入探讨字符串的基础、编码模式以及不同类型字符串之间的转换方法。 #### ...
- Ansi字符串:每个字符占用一个字节,以单字节0结尾。例如,"Bob"在内存中存储为426F6200。 - Unicode字符串:每个字符占用两个字节,以双字节0000结尾。L"Bob"在内存中存储为42 00 6F 00 62 00 00 00。 - DBCS字符...
【VC学习笔记与C++字符串完全指引】 在深入探讨VC学习笔记和C++字符串的使用时,我们首先需要了解Visual C++(简称VC)的历史和发展。VC6是Microsoft开发的一个经典版本,它在1998年发布,以其强大的集成开发环境...
4. **数组与字符串**:C++中的数组用于存储同类型的数据集合,字符串是字符数组的特殊形式。了解数组的动态分配和字符串处理函数是必不可少的。 5. **结构体与联合体**:结构体允许组合不同数据类型创建复合数据...
在Vim中,通过启用特定的语法文件,可以使得C和C++代码中的关键字、常量、字符串等元素以不同的颜色显示,这样不仅能帮助我们快速识别不同类型的代码元素,还能减少语法错误。例如,在vimrc中添加以下行来开启C和C++...
这些只是C++20规范中的一部分亮点,实际规范中还有更多细节和改进,包括字符串查找、并行算法、可选值(std::optional)和预期值(std::expected)的改进等。"**c++20标准.pdf**"文档将详细解释所有这些内容,为C++...
学习者可以在基础的算术运算、字符串操作、数组处理等领域找到对应的示例,也可以探索更高级的主题,如递归算法、文件操作以及复杂的面向对象编程。这种从简单到复杂、从基础到进阶的程序设计,使得学习者能够循序渐...
10. **标准库和库函数**:介绍C++标准库中的各种函数,如输入/输出流、字符串处理、时间管理等。 通过这个压缩包中的CHM文件,开发者不仅可以系统地学习C++编程,还可以查询特定问题的解决方案,提升在VC6.0环境下...
- **修改文档模板字符串**:在资源视窗中选择`String Table`项,双击`IDR_MAINFRAME`项来修改相关的字符串。 以上介绍了MFC应用程序开发中的一些关键知识点和技术细节,对于学习和掌握MFC框架来说是非常有用的。...
例如,为模板`template <typename T> void print(T val)`提供`void print(std::string val)`的特化版本,以优化字符串的打印。 - **模板偏特化**:对于模板模板参数的部分,可以进行偏特化。比如,对`template ...
- 字符串处理 - 引用 - 动态内存管理(new、delete) 2. 面向对象编程(OOP) - 类和对象 - 继承(公有、私有、保护继承) - 多态(虚函数、纯虚函数、抽象类) - 封装(访问修饰符、构造函数、析构函数) ...
- 将字符串字段转换为相应的数值类型(如浮点数或整数)。 - 根据NMEA规范,验证和解析每个字段,例如检查日期和时间格式,计算经纬度、高度等。 - 存储解析后的数据,供后续应用使用。 5. 实践应用: 解析GPS...
1. 初始化字符串:创建一个以"$"开头的字符串。 2. 填充字段:根据内部数据结构填充各个字段。 3. 计算校验和:根据NMEA规范计算并添加到字符串末尾。 4. 格式化输出:确保字符串符合NMEA标准,例如正确处理度分秒...
MFC提供了CString类来处理字符串,我们可以使用它来存储用户输入的数值,然后通过转换函数如ATOF将其转化为浮点数进行计算。同样,计算结果也可以先转化为字符串,再显示到编辑框中。 计算器还涉及到一些特殊功能,...
4. **数据类型转换**:讲解如何处理数据库中的不同数据类型,如整型、浮点型、字符串等,以及如何在C/C++中进行数据类型转换。 5. **安全性和性能优化**:讨论UDF的安全性问题,如权限控制、并发执行下的线程安全,...