Delphi编程基础 之 字符串篇
来源:互联网 发布:淘宝店铺名片怎么改 编辑:程序博客网 时间:2024/04/30 17:17
本文整理了 Delphi字符串格式 ShortString 、AnsiString、WideString。以及PChar、Char数组的使用方法及需要注意的地方,很多例子来自网络。
本文所有例子基于Delphi7,使用例子如有不对之处,欢迎指正。
参考文献:delphi7 开发指南;
(一) ShortString
ShortString 的存储结构如下:
+---------------------+
| 1Byte | 字符串内容 |
+---------------------+
0 1
其第一个字节为字符串的长度,所以ShortString 的长度不能超过255,其存储区为静态分配,大小在编译时确定,这是继承于BP for Dos 的类型。保留该类型是为了向后兼容Delphi 1.0,和为了与Pascal 传统string 相兼容而保留的。但是这个字串数组的最后是没有一个#0 字符作为结尾的,因此ShortString 和C 语言的字符串是不兼容的。
(二)AnsiString
Delphi2.0 以后引入了AnsiString,,它是一个容易使用而且没有2 5 5 个字符限制的字符串类型。
而且它并不需要以NULL 结尾,因为有长度信息,同样因为这个字符串内可以包含任意的NULL 而不会被认为是字符串结尾。并且AnsiString 与n u l l 结束的字符串相兼容。其存储结构如下:
+-----------------------------------+
| 4B | 4B | 4B | 字符串内容 |
+----------------------------------+
-12 -8 -4 0 ... ...
内存偏移-12 处为该字符串分配的内存大小、内存偏移-8 处为该字符串的引用计数,内
存偏移-4 处为该字符串长度。AnsiString 字符串最大长度2G
AnsiString 是Delphi 独有的,其存储区在运行时动态分配的并有自动回收功能,因为这个功能A ns i S t r i n g 有时被称为生存期自管理类型。
当两个或更多的A n s i S t r i n g 类型共享一个指向相同物理地址的引用时,Delphi 使用
了Copy – On - Wr i t e 的技术,即一个字符串要等到修改结束,才释放一个引用并分配一个物理字符串。下面的例子有助于理解这些概念:
我们平常使用的String 类型,在默认的情况下就是AnsiString;我们可以通过Huge Strings 的编译选项来将String 类型定义为ShortString,即将编译选项$H 设为负值。在缺省情况下编译选项$H 为正值,即String 类型为AnsiString。
在使用AnsiString 是要注意以下几点:
一、$H 有一个例外。
使用$ H 规则的一个例外是,如果在定义时特地指定了长度(最大在2 5 5 个字符内),那么总是S ho r t S t r i n g。
二、免重复初始化。
由于AnsiString 会自动初始化为空。如下代码中的初始化就纯属多余了。
s:='';就完全没有必要。但是值得注意的是这对函数返回值Result 无效。而一般说来,用var 实参传递比返回字符串值要更快一些。
三、用SetLength 预分配长字符串(AnsiString)。
虽然动态分配内存是AnsiString 的一大长项,但有时候反而会降低效率,还是要用到SetLength 来为AnsiString 类型的字符串来分配内存。请看如下例子。
当然此例可用Delete 取代之,这里主要说明在上例的循环中s2 的内存区域被不停地重复分配,降低效率。一个简单有效的办法如下:
这样s2 内存只会重新分配一次。
四、量避免使用ShortString
因为再Delphi 中很多字符串操作会先把ShortString 转换为AnsiString,从而减慢了执行速度,因此还是少使用短字符串为妙。
五、避免使用Copy 函数
这也和滥用内存管理有关。一个典型的情形如下:
if Copy(s1,23,64)=Copy(s2,15,64) then ……
这样导致分配了两块临时内存,因而降低了效率。应当替换为如下代码:
同样的,如下语句就显得相当低效:
s:=Copy(s,1,length(s)-10);
应改为
Delete(s,length(s)-10,10);
六、尽量使用AnsiString,必要时转换为Pchar
先看看AnsiString 的定义:
其中Astring[1]将返回Astring.ChrArr[1]的内容。
很多人认为AnsiString 是天生低效的。其实这在很大程度上是由代码编写不良、内存管理乱用和缺乏支持的函数所致。如上所述,一旦被动态分配了一块内存,长字符串就成了一个线性的字节序列,并无所谓的效率问题。当然,若有更多有效的函数支持那就更好了。
说到AnsiString 到PChar 的转换,本质上有三个办法:
(1) P:=@s[1];这会引发UniqueString 调用,UniqueString 使字符串拥有唯一的存储区域。
(2) P:=PChar (s);这会先检查s 是否为空,若是,则返回nil,否则即返回s[1]的地址。
(3) P:=Pointer(s);这不会引发任何隐含调用,因而是在确定s 非空情况下的最佳选择。
(三)Pchar
Pchar 就是纯指向字符串(#0 字符结尾)的指针,与C 语言中的char *是一样的。定义时由Delphi
自动填0。PChar 主要是为了兼容各类API,在Delphi 中更加广泛应用,其存储区可以用字符数组静态分配,也可用GetMem 手动分配。
(四)Char 数组
Char 数组也是指向字符串的指针,它与Pchar 的区别在于:
1. Char 数组(均指非动态数组)一旦定义好,它的长度就固定了;
2. Char 数组的地址是常量,不能另赋其它值,不能像Pchar 一样
(五)WideString
WideString 长字符串类型与ANSIString 类型相似,只是它基于WideChar 字符类型,WideChar
字符为双字节Unicode 字符。但是Delphi 的vcl 是使用AnsiString 实现的,所以使用WideString 在Delphi 中实际使用会很不方便,这里不详细介绍了。
(六)一些例程
下面举一些具体的例子,有助于帮助我们理解Object Pascal 关于字符串的一些基础概念。
最好先不要用Delphi 调试。看一下个过程中ShowMessage()中的返回值。
//题1
分析:答案为PChar(s)[0] := 'm';引起内存访问冲突。因为对于像 s1:='abcde' 或者
ShowMessage('wxyz') 这样的语句,常数字符串是放在代码段(CODE Segment)中的,在32 位保护模式下代码段是不能直接写入的。
//题2
分析:答案为mbcde。代码和1 题差不多,但是s[1] := 'v';引起了字符串的Copy-On-Write 的机制为S分配了新的空间,所以可以安全的运行。
//题3
分析:答案为mbcde。由于字符串的Copy-On-Write 的机制,字符串刚赋值后,实际上是指向同一块内存只是增加了引用计数,所以用这种方式修改字符串2,也就是修改了字符串1。
//题4
分析:答案为26。AnsiString 的定义可以知道,AnsiString 并不需要以NULL 结尾,因为有长度信息,同样AnsiString 内可以包含任意的NULL 而不会被认为是字符串结尾。
//题5
分析:答案20。注意,这种操作在编程中和4 题的结果是不同的。Pchar 是以“#0”作为字符结尾的。
//题6
分析:答案为hello world.15。这里要注意的是:字符串赋值时复制的字符数只和字符串的长度有关,同时注意ShortString 和AnsiString 在0 位置元素上的区别,ShortString 的实际长度由0 位置的字符决定。
//题7
分析:答案为zabcdefghijklm:714。这里要注意字符串在传递给无类型可变参数时的区别,
ShortString 变量的地址实际表示0 元素的地址,传递给无类型可变参数时应写为S[1], 而AnsiString是一个指针,指向一个字符串变量的数据区,传递给无类型参数时,应为PChar(s)^ 或者 s[1]
//题8
分析:答案为BMMMMMMMMM,后面可能会有不可预料的内容出现,因为没有#0 结尾,同时注意Move(s1, s2[0], 10); s1 是短字符串,引用s1 会发生内存溢出,修改s3 也相当于修改s2。
- Delphi编程基础 之 字符串篇
- windows内核编程基础篇之字符串的处理
- windows内核编程基础篇之字符串的初始化
- Windows内核编程基础篇之字符串的拷贝
- Windows内核编程基础篇之字符串的连接
- Windows内核编程基础篇之字符串的打印
- Windows SDK编程(Delphi版) 之 应用基础,楔子
- Delphi之字符串
- 05:输出亲朋字符串( 1.7编程基础之字符串)
- 19:字符串移位包含问题(1.7编程基础之字符串)
- 26:字符串最大跨距(1.7编程基础之字符串)
- WINDOWS编程技巧之DELPHI篇
- WINDOWS编程技巧之DELPHI篇
- WINDOWS编程技巧之DELPHI篇
- windows编程技巧之delphi篇
- WINDOWS编程技巧之DELPHI篇
- Python字符串之基础篇
- python基础篇之字符串
- 用CMMI指导需求管理
- 一个"渔民"转身变成了个"程序员"
- windows编程字符串处理小结
- 2009年8月1日至顶网zdnet研发中的非研发管理俱乐部第2次沙龙——有几种领导就有几种研发考核
- 软件工程不是想象中那么简单
- Delphi编程基础 之 字符串篇
- 数据库管理常用命令
- 编程好学吗,学完能做什么,怎么学才好?
- Chapel 0.9 -- variable length arguments函数中的参数类型推导
- Red Hat Enterprise Linux 4 JDK1.6+TOMCAT6安装配置文档
- C和OpenGL结合生成钻石图形的解决方案
- java jdk和sdk安装
- 微软的面试题及答案-超变态但是很经典
- 短信笑话