Delphi 中的字符串——《Delphi6 开发人员指南》读书笔记

Laravel迁移与填充实现跨数据库抽象层 数据库抽象层是现代PHP应用工程化的核心能力,其本质是通过统一接口屏蔽MySQL、PostgreSQL、SQL Server等底层差异,实现结构定义与初始数据的可复现、可切换、可协作。其技术原理依赖Schema Builder的语法翻译机制和Query Builder的驱动适配能力,将DDL操作转化为数据库无关的PHP代码逻辑,从而赋予应用真正的多库兼容性。这种抽象不仅提升开发效率,更显著降低测试、部署与客户定制场景下的运维成本。在Laravel中,迁移(Migrations)负责表结构与约束的版本化管理, 阅读详情

Delphi 中的字符串

——《Delphi6 开发人员指南》读书笔记

Spacesoft【暗夜狂沙】

Delphi 对字符串这个结构的支持是十分丰富的,不仅有Delphi 本身支持的string 类型,还支持和C 语言兼容的字符串数组。那么他们之间有什么区别呢?本文试图就此做一个详细的剖析,并且试图回答论坛上常见的几个问题。

首先,我们要讨论的是Delphi 中的string 到底是什么东东,因为我们在OP 的语法参考手册上知道,Delphi 有三种string : ShortString、AnsiString (就是兼容BCB 的AnsiString 的那种)以及WideString (用来支持Unicode 的,其他的和AnsiString 是完全一样的)。在默认的情况下,编译器将把string 解释为AnsiString ,而需要的时候,可以设置使编译器将string 解释为ShortString(当然,我们很少见到人要这么做,因为AnsiString 用得很好,而ShortString 只支持255 个字符,并且和C 语言的字串数组不兼容,这个我们后面会提到),对应的编译器指示符号是默认的{$H+} 和 {$H-}。

那么,这三种string 到底有什么差别呢?差别在于他们的不同结构。

对于ShortString 来说,它在内存中的结构可以表示为:

strShort = record
    wLength: WORD;
    szBuf: array of Char;
end;

也就是说,对ShortString 的每次操作,不需要遍历这个字符串便可以取得这个字串的大小了。另外,这个字串数组的最后是没有一个#0 字符作为结尾的。因此ShortString 的数组和C 语言的字符串是不兼容的。


对于AnsiString 来说,根据《Delphi6 开发人员指南》的描述,它的结构可以表示如下:

strAnsi = record
   nSize: Integer;
   nRef: Integer;  
   nLength: Integer;
   szBuf: array of Char;
end;

也就是说AnsiString 不仅仅保存了本字串的长度,还保存了对这个字符串的引用数。因此,不同的AnsiString 事实上可能具有相同的物理地址,所以Delphi 的字符串拷贝经常是效率惊人的。然而,当一个字符串改变时怎么办呢?Delphi 将释放对这个字符串的引用(把nRefCount 减1),然后新建一个字符串来装载新的内容。

另外,与ShortString 不同的是,AnsiString 的字符数组是以#0 结尾的,这样szBuf 就可以被当成C 中的字符数组了。估计这样的设计是为了兼容Win32 API。

WideString 和AnsiString 基本上是一样的,所以我们讨论的时候,仅仅讨论AnsiString 和ShortString。

然后, 我们要说明的是,string 具有生存期管理特性。就是说,当string 超出作用域后,字符串占用的资源自动被释放掉。这个机制是怎么实现的呢?对于全局变量,当然它的作用域就是它所在的Unit 的生存周期,那么当然可以在finalization 段进行释放了。而函数中的变量呢?编译器就自动在整个函数的外面套上一个try ... finally 处理。这样,不管什么情况下,这些变量就总能释放掉了。

下面一个问题是:假如现在有一个指针,它被指向一个string, 那么它指向的东西是什么呢?

答案是:指向szBuf 的开头,并且ShortString 不支持这样的强制转换(这是很自然的,因为做这样转化的目的纯粹就是为了和C 语言兼容)。于是string[1] 就是这个字符串的第一个字符。于是,“看起来”这个字符串就只有那些字符了。于是,我们就可以用PChar() 强制类型转化把一个string 转化为一个PChar,然后传到需要字符数组作为参数的Win32 API 中,因为“看起来” 这个字符串这个时候确实是一个标准的C 语言字符串。甚至,我们可以这样使用字符串:

procedure Test();
var
    strBuf: string;
begin
    SetLength(strBuf, 255);  //千万不要忘了先给你的字符串申请足够的空间,不然……嘿嘿,等着弹框儿吧^_^
    GetModuleFileName(0, PChar(strBuf), 255);
    ShowMessage(strBuf);
end;

我们知道,这个API 的原型是这样的:

DWORD GetModuleFileName(
  HMODULE hModule,    // handle to module
  LPTSTR lpFilename,  // Pointer to a buffer that receives the fully-qualified path for the module
  DWORD nSize         // size of buffer
);

这个API居然以为我们真的根据它的要求传了一个array of Char 进去!

通过类似这样的机制,Delphi 使它的使用者在C 语言写的API 原型中可以自由的穿行,一点都没有“二等公民”的感觉,而且又可以享用Delphi 本身的数据类型带来的方便,了不起!

现在我们来总结一下Delphi 中字串类型的特点:

1、与C 语言不同,不是依靠#0 字符做字串结束标志,而是通过字串前面的数字来记录字符串的长度(尽管为了和C 语言兼容,AnsiString 的字串实现确实是在结尾放了一个#0 字符的)
2、string 是具有生存期管理特性的,当string 超出作用域后,字符串占用的资源自动被释放掉。
3、对字符串进行强制类型转化为PChar ,会得到一个字符串指针,这个字串指针的用法和C 语言中的数组是一样的。
对于
    strBuf: string;

    SetLength(strBuf, 255);
你在使用时,可以把PChar(strBuf) 看作是C 语言里的这样一个东西:

    char strBuf[255];

记住,在上个声明里strBuf 是一个指针,它指向那个指针数组的第一个字符的地址,而你做PChar(strBuf) 运算得来的指针就是这个东西。

在最后,解释一下《开发人员指南》里面引起过一段争论的一句话:

“在练习将一个字符串转换为PChar类型时要小心,因为字符串在超出其作用范围时有自动回收的功能,因此当进行P:=PChar(Str)的赋值时,P的作用域(生存期)要比Str 长。”

这句话的意思是这样的:字符串类型是具有自动回收功能的,但是字符串指针没有。P:=PChar(Str)返回的指针可能在作用域之外使用,因此P 的生存周期可能比Str 要长。举个例子来说明:


procedure getPChar(P: PChar);
var
    strTmp: string;
begin
    strTmp := 'asasass';
    P := PChar(strTmp);
end;

这个时候,明显返回的这个指针P 的作用域要大于strTmp,那么这个过程结束的时候,strTmp已经被自动释放掉了。调用这个过程的函数得到的P 事实上已经是一个悬挂指针,没有意义了。作者的本意是提醒读者注意防止这样的情况发生。

参考文献:

1、《Delphi6 开发人员指南》,Steve Teixeira 等著,龙劲松等译,机械工业出版社,北京,2003年1月第一版

2、《Object Pascal 语言参考手册》

欢迎光临作者的个人主页:http://www.mrspace.net/

Delphi语言的字符串处理 Delphi是一种强大的编程语言,以其易于使用的视觉界面和强大的数据处理能力而闻名。在应用程序开发中,字符串处理是一个至关重要的部分。无论是在开发桌面应用程序、数据库应用程序还是Web应用程序,字符串都在数据输入、存储和输出过程中扮演着重要的角色。本文将深入探讨Delphi语言中的字符串处理,包括字符串的基本操作、函数、处理技巧与示例。 阅读详情

相关推荐

Delphi中实现字符串分析:统计数字、字母、空格及其他字符个数

在Delphi中,字符串是由字符构成的序列,字符的种类繁多,除了数字、字母和空格之外,还有许多其他类型的字符。例如标点符号、运算符、货币符号等。它们在不同的应用场景中具有特定的含义。在进行字符统计时,我们常常需要将这些"其他字符"单独识别出来。为了提高代码的复用性和可读性,我们可以设计自定义函数来进行字符的分类统计。这不仅可以简化主程序代码,还可以使功能模块化。beginend;end;

weixin_42356162的博客 1048

093_《Delphi6实用开发指南》

Delphi 6.0是Borland公司最新推出的新一代可视化开发工具,它具有功能强大、简便易用和代码执行速度快等优点。业界人士一致认为:真正的程序员用C,聪明的程序员用DELPHI。 全书分为18章,内容包括:Delphi概述、Delphi的集成开发环境、ObjectPascal语言基础、常用组件、对话框设计、多文档使用、窗体设计、图形图像处理、多媒体应用、文件管理、异常处理、API函数的应用、使用和创建Activex组件、对象的链接与嵌入、数据库环境、数据库访问组件和数据库感知组件。本书内容丰富,介绍详

敦格 3045

《Delphi6开发人员指南》中文版 (超星格式)

此书是《开发人员指南》系列的最新中文版,是Delphi程序员必备的工具书。这一版本在《Delphi5开发人员指南》一书的基础上,增加和改写了大部分内容。注:此书为PDG格式电子书,需超星浏览器3.8以上的版本,才能阅读。

delphi遍历record 各个属性和值

通过rtti遍历record,支持delphi2010以上版本,更低版本不支持。可以遍历record的field的名称、类型和长度。delphi遍历record。

百万软件 918

Delphi6开发人员指南(PDF)

Delphi6开发人员指南(PDF) delphi程序员入门必读。绝版。pdf格式可能不是很清晰

Delphi6开发人员指南.pdf

一本学习Delphi6的经典书籍,一书在手,万事不忧!

Delphi 中的字符串——《Delphi6 开发人员指南》读书笔记 (转)

Delphi 中的字符串——《Delphi6 开发人员指南》读书笔记 (转)[@more@]Delphi 中的字符串 ——《Delphi6 开发人员指南》读书笔记 Spacesoft【暗夜狂沙】 Delphi 对字符串这个...

csd3176的博客 87

【ESP32-S3量产指南】基于Flash下载工具实现Release模式Flash加密与安全配置

本文详细介绍了ESP32-S3量产阶段如何通过Flash下载工具实现Release模式下的Flash加密与安全配置。从加密模式选择、工具配置到分区表优化,提供了一套完整的量产安全解决方案,帮助开发者有效防止固件泄露和篡改,确保设备安全。

weixin_28730131的博客 230

读书笔记:Delphi5开发人员指南 第二章(1)

最近上班总有一些零散的事情要处理,要负责同事们电脑的日常维护,以及一些软硬件方面的问题。所以就没有太多的时间用来读书。而且更加郁闷的是,上周末由于访问一个网站造成电脑中毒,尝试了很多方法清除都未能成功。病毒文件在安全模式下删除后重新启动又恢复了,修改注册表中的run也无效,几番修改也告失败。最终在判断方面出现错误,将系统文件误认为病毒文件删除,导致系统无法启动。最后只好ghost回去,无奈人太懒,

我的技术笔记 1470

如何使用ArcGIS自动矢量化建筑

在显示的重分类对话框内,输入栅格选择提取单波段后的栅格,重分类分为三个层级,旧值分别为100-249、250-251和252-255,对应新值为1、2和3,旧值的最小和最大值不用修改,保持和原有的一致。同样在ArcToolbox内点击Spatial Analyst工具点击“重分类\重分类”,在重分类对话框内输入栅格选择之前重分类过后的图片,将旧值3的新值设置为1,这样分类后就只有两类。在显示的新建Shapefile对话框内,名称命名为折线,要素类型选择折线,点击编辑,设置坐标系为WGS 1984。

2163

深度探索:机器学习中的最大似然估计(MLE)原理及其应用

最大似然估计作为统计推断的核心方法,在机器学习领域具有广泛的应用价值和深远影响。尽管存在对模型假设敏感、易受异常值影响等局限性,但其直观的原理、坚实的理论基础以及高效的实现方式使其在实践中仍占据主导地位。随着深度学习、强化学习等新兴领域的快速发展,最大似然估计将继续演化并适应新的模型结构与优化框架。同时,结合现代优化算法、并行计算技术以及贝叶斯方法的融合,最大似然估计有望在保持其核心优势的同时,进一步提升参数估计的准确性和鲁棒性,为未来的机器学习研究与应用开辟更广阔的道路。

qq_51320133的博客 1万+

《 delphi 6 開發者手冊 》讀書筆記(1)

 1.常量的定義通過關鍵字 const 來聲明,比如    const          pi=3.14         number=10000         book=delphi 2.變數的定義需要注意兩點。(a)1.變數名要符合object pascal語言關於標識符的規則。(b)必須明確指定變數的類型,可以是預定義的標準類型,也可以是前面自己聲明過的自定義類型。

兔子吃南瓜 845

Dify整合FireCrawl与百度搜索实战:手把手教你打造全能研究助手

本文手把手教你基于Dify平台,整合FireCrawl网页爬虫与百度搜索能力,构建一个能同时处理本地文档与实时网络信息的全能研究助手。通过部署核心环境、配置模型、接入两大工具并设计自动化工作流,实现从问题提出到深度分析报告生成的一站式解决方案,极大提升信息调研与整合效率。

weixin_29062963的博客 500

我的写作感悟暨Unix编程需要学习的内容(1)《精通Unix下C语言与项目实践》读书笔记(11)...

《精通Unix下C语言编程与项目实践》读书笔记(new) 文章试读 不拘一个遍程序系列:编程序不能一个脑袋钻到底,有时要学会变通,即所谓的曲线救国。一、二、三、四 职场规划:一些杂七杂八的职场感悟吧。不值钱的软件人才精力充沛与事业成功让系分来得更猛烈些吧不值钱的系统分析师经济危机下大学生如何就业经济危机中如何提高...

weixin_34161029的博客 164

SRAM Bank数量配置:性能、面积与功耗的权衡指南

SRAM(静态随机存取存储器)是芯片设计中的关键存储单元,其Bank数量配置直接影响访问延迟、吞吐率、功耗和面积。Bank切分通过将存储阵列分区,缩短位线和字线延迟,从而提升性能,但会增加外围电路开销。合理配置Bank数量可优化PPA(性能、功耗、面积),在28nm和16nm工艺下,2个Bank通常是性价比最高的选择。本文基于实测数据,探讨不同场景下的Bank配置策略,帮助工程师避免常见误区,提升设计效率。

weixin_27230891的博客 179

ArcGIS基础:城市交通网络构建及设施服务分析(一):道路数据处理与拓扑操作

首先需要加载数据, 1:选择这个数据库:,右键导入,选择导入单个要素,弹出“要素类至要素类” 2:输出位置(导入的数据是CAD格式数据)。 3:输出要素类为道路。 4:字段只保留道路类型字段。 这个操作是分类合并各级道路数据。 1:通过属性选择各类道路数据。 2:比如此类都是“干道”。 3:编辑器下来,然后合并即可。 得到如图所示,需要用到三个字段。 上面这个操作是打断道路相交线。 1:选中所有数据。 2:找到高级编辑中的打断相交线。 3:确定即可。 下面进行拓扑检查,虽然我们已经进行合并和打断相交.

yuanYW7556的博客 2万+

Windows编程之进程的创建

本文原创,最早发表于公司内部博客, 禁止转载 文章目录前言一. PE文件格式简介1.1. 基本概念1.2. MS-DOS头1.3. PE文件头1.4. 区块二. R0和R3三. 进程虚拟地址空间3.1. 进程隔离3.2. 虚拟地址空间介绍3.3. 虚拟地址空间分区3.4. 分页3.5. VirtualAlloc、HeapAlloc、malloc、new四. 进程的创建和运行4.1. 进程的创建4.2. 内存映射文件4.3. 工作集(working set)4.3. 页错误4.4. 写时复制4.5. 页文件后

Just_bg的专栏 1619

Tesla v100 4张显卡组装机安装vllm和ollama在Ubuntu系统上的安装---AI大模型系统从零开始0032

本文提供Ubuntu22.04系统下vLLM的完整安装指南,适配4×32G Tesla显卡的单机4卡张量并行部署。教程包含:1)硬件要求(Ubuntu22.04、NVIDIA驱动≥535、CUDA12.1+);2)NVIDIA驱动自动安装方法;3)Python3.10虚拟环境配置;4)vLLM官方预编译包一键安装;5)单机4卡启动Qwen3.6-27B模型的完整参数说明(含FP8量化、多进程并行等关键配置)。文末附分布式部署的Ray集群方案参考链接,适用于多机8卡场景。

添柴程序猿的专栏 176

算法设计 - LCS 最长公共子序列&&最长公共子串 &&LIS 最长递增子序列

虽是读书笔记,但是如转载请注明出处 http://segmentfault.com/blog/exploring/ .. 拒绝伸手复制党 本章讲解: 1. LCS(最长公共子序列)O(n^2)的时间复杂度,O(n^2)的空间复杂度; 2. 与之类似但不同的最长公共子串方法。 最长公共子串用动态规划可实现O(n^2)的时间复杂度,O(n^...

weixin_34375054的博客 451

手把手写深度学习(27):如果获得相机位姿态的plücker embedding?以RealEstate10K为例

用plücker embedding表示相机的位姿是一种非常常用的方法,这篇博客以RealEstate10K数据集为例子,详细讲解如何从相机的轨迹坐标中获得plücker embedding,用于下一步模型的学习。

沉迷单车的追风少年 2239

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

delphi 字符串截取

'123456'.Substring(1, 2)='23' //从0开始 copy('123456,1,2)='12' //从1开始

3111

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Delphi 字符串截取函数

如果要使用LeftStr,RightStr,MidStr必需引用系统单元StrUtils; 声明变量Str:string; Str:=HelloWorld; 1,LeftStr(Str,2)=He;//从Str字符串变量的最左边(第一个字符包括第一个字符)开始截取2个字符; 2,RightStr(Str,2)=ld;//从Str字符串变量的最右边(第一个字符包括第一个字符)开始截取2个字符...

weixin_30325487的博客 493

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

#数字表示什么

#0表示没有任何内容(并不等同於空字符,相当於没有做任何操作一样)。 比如: #13表示回车(Enter) #8表示退格(Back Space) #32表示空格 #49表示‘1’ ...... 如果用带#来表示键盘输入的内容(如上),那麼#0表示什麼都没输入(相当於没有敲键盘)。

云中雁012345之成长 8544

Delphi遍历ADO数据集遍历操作

delphi中遍历ado数据操作

qq_45083002的博客 1726
上一篇: 大腕之过度设计
下一篇: 《东邪西毒》之IT求职版
Spacesoft
博客等级 码龄23年 0粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值