百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

Delphi基础教程图文版之字符串详解

yuyutoo 2024-12-31 15:36 11 浏览 0 评论

上午在整理多线程的文章,没注意时间今天发晚了,最近争取日更!!

Delphi中的字符一直处于懵懵懂懂的状态,不同于我接触到的其它编程语言在Delphi中居然有好几种字符串,今天好好研究一番!!

Delphi中字符串的操作很简单,但幕后情况却相当复杂。Pascal传统的字符串操作方法与Windows不同,Windows吸取了C语言的字符串操作方法。

32位Delphi中增加了长字符串类型,该类型功能强大,是Delphi缺省的字符串类型。

传统的字符串类型是一个字符序列,序列的头部是一个长度字节,指示当前字符串的长度。由于只用一个字节来表示字符串的长度,所以字符串不能超过255个字符。

这一长度限制为字符串操作带来不便,因为每个字符串必须定长(确省最大值为255),当然你也可以声明更短的字符串以节约存储空间。 为克服传统Pascal字符串的局限性,32位Delphi增加了对长字符串的支持。这样共有三种字符串类型:

ShortString

短字符串类型也就是前面所述的传统Pascal字符串类型。短字符串中的每个字符都属于 AnsiChar类型(标准字符类型)

var
  S: ShortString;   { 255个字符长度,256个字节}
  S1: String[255];  { S1和S的字符类型一样}
  Len: Integer;
begin
  S := 'Hello';
  Len := Ord(S[0]); { Len现在包含S的长度为5,Ord函数可以把一个字符类型转换为整数类型}
  Len := SizeOf(S); { Len现在包含的是ShortString类型的大小,为256字节} 
end;

以上例子通过S[0]可以获得S的字符串长度,当然也可以用Length函数来确定一个短字符串的长度。

可以通过数组的下标来访问ShortString中的一个特定位置的字符,具体使用参看下面例子和注释说明:

var
  S: string[8];
  i: Integer;
begin
  S := 'a_pretty_darn_long_string';
  { 因为S只有8个字符大小,因此s的实际存储的内容为"a_pretty"}
  i := 10;
  S[i] := 's';
  { 因为S只有8个字符大小,试图改写第10个元素,将会使内存混乱}
end;

AnsiString

这种类型也有人称为长字符串类型(LongString)同时也是Delphi默认的字符串类型,它是一种动态分配的字符串,其大小只受可用内存的限制。声明一个长字符串,只需要用关键字String不加大小参数即可。据说使用了更新前拷贝(copy--on-write)技术。恕我才疏学浅没研究过这个东西。这类字符串长度没有限制(可以存储多达20亿个字符),其字符类型也是AnsiChar类型。

由于是动态分配的,一次可以随意修改字符串,而不用担心对其他的影响,也不用担心越界的问题。String类型没有0元素,试图存取String类型的0元素会产生一个编译错误。

之前在万一老师的博客中看到了以下的代码不太理解,现在可以完全解释为什么我们试图将一个string类型的变量直接赋值给字符数组时报错了

//字符串 < > 字符数组,注意这里说的字符串仅仅是长字符串
var
  arr: array[0..5] of Char;
  str: string;
begin
  {可以把字符串常量直接赋给字符数组; 但超界不行}
  arr := 'Delphi';
  ShowMessage(arr); {Delphi}

  {可以把字符数组直接赋给字符串变量}
  str := arr;
  ShowMessage(str); {Delphi}

  {其实字符串内部也是包含了一个字符数组, 所以能索引访问, 不过它的索引起始于 1}
  ShowMessage(str[1]); {D}
  ShowMessage(arr[0]); {D}

  {但不能把一个字符串变量赋给字符数组}
  //arr := str;     {错误; 这需要用其他手段实现, 譬如复制或移动内存}
end;

WideString

长字符串类型与AnsiString 类型相似,只是它基于WideChar字符类型,WideChar字符为双字节Unicode字符。

var
  S: string;
  { 在Delphi 7中默认string等同于AnsiString}
  WS: WideString;
begin
  S := '世界你好';
  WS := S;
  ShowMessage(S[1]);  { 此时无任何显示,因为S[1]取出的是‘世’的一半}
  ShowMessage(WS[1]); { 显示‘世’}
end;

不过WideString和AnsiString的不同主要在三个方面:

  • WideString由WideChar字符组成,而不是由AnsiChar字符组成的,它们跟Unicode字符串兼容。
  • WideString用SysAllocStrLen()API函数进行分配,它们跟OLE的BSTR字符串相兼容。
  • WideString没有引用计数,所以将一个WideString字符串赋值给另一个WideString字符串时,就需要从内存中的一个位置复制到另一个位置。这使得WideString在速度和内存的利用上不如AnsiString有 效。

Ansi和Unicode

字符编码:为了区分一个字符到底使用了几个字节,就不能将字符的编号直接存储到计算机中,字符编号在存储之前必须要经过转换,在读取时还要再逆向转换一次,这套转换方案就叫做字符编码。它规定了如何将字符的编号存储到计算机中

字符集:为每个字符分配了唯一的编号。可以将字符集理解成一个很大的表格,它列出了所有字符和二进制的对应关系,计算机显示文字或者存储文字,就是一个查表的过程。它定义了字符和二进制的对应关系

ASCII(American Standard Code for Information Interchange,美国信息交换标准码),它使用7 bits来表示一个字符,总共表示128个字符,后来IBM公司在此基础上进行了扩展,用8bit来表示一个字符,总共可以表示256个字符

ANSI(American National Standard Institite)美国国家标准学会(美国的一个非营利组织),首先ANSI编码是一种对ASCII码的拓展,它不是指的一种特定的编码,而是不同地区扩展编码方式的统称,各个国家和地区所独立制定的兼容ASCII但互相不兼容的字符编码,微软统称为ANSI编码

Unicode 是一套字符集,而不是一套字符编码。它固定使用16 bits(两个字节)来表示一个字符,共可以表示65536个字符。标准的Unicode称为UTF-16。后来为了双字节的Unicode能够在现存的处理单字节的系统上正确传输,出现了UTF-8

个人理解:ANSI是每个国家根据自己的语言在ASCII基础扩展的一些编码。为了实现大一统出现了Unicode,而Unicode为了兼容以前的字符出现了双字节(UTF-16)和单字节(UTF-8)之分

PChar和字符数组

在第二季的视频中我曾经对端口号做过一次转换sin_addr.S_addr := inet_addr(PAnsiChar(AnsiString(EditAddr.Text))); 这段代码,一个将字符串转成PAnsiChar的一个场景,这是个什么玩意儿?其实这样做纯粹是为了兼容winAPI中的数据类型

在C和C++中没有真正的字符串数据类型,都是通过以Null结尾(0)的字符数组来实现的,字符数组没有长度字节,因此只能通过结尾的Null标志来作为字符串的字符结束标志。又因为Windows是用C编写的,很多Windows函数要用到以字符数组作为参数,但Pascal字符串类型不是字符数组,因为为了让Pascal字符串也能与Windows兼容,就需要一个字符串数组,PChar类型正是符合这种需求,在任何需要字符数组的地方都可用PChar。相应的也有PAnsiChar和PWideChar,分别对应于AnsiChar字符和WideChar字符。

其实最初我也被字符串折腾的不行不行的,所以整理这篇文章

相关推荐

当 Linux 根分区 (/) 已满时如何释放空间?

根分区(/)是Linux文件系统的核心,包含操作系统核心文件、配置文件、日志文件、缓存和用户数据等。当根分区满载时,系统可能出现无法写入新文件、应用程序崩溃甚至无法启动的情况。常见原因包括:...

玩转 Linux 之:磁盘分区、挂载知多少?

今天来聊聊linux下磁盘分区、挂载的问题,篇幅所限,不会聊的太底层,纯当科普!!1、Linux分区简介1.1主分区vs扩展分区硬盘分区表中最多能存储四个分区,但我们实际使用时一般只分为两...

Linux 文件搜索神器 find 实战详解,建议收藏

在Linux系统使用中,作为一个管理员,我希望能查找系统中所有的大小超过200M文件,查看近7天系统中哪些文件被修改过,找出所有子目录中的可执行文件,这些任务需求...

Linux 操作系统磁盘操作(linux 磁盘命令)

一、文档介绍本文档描述Linux操作系统下多种场景下的磁盘操作情况。二、名词解释...

Win10新版19603推送:一键清理磁盘空间、首次集成Linux文件管理器

继上周四的Build19592后,微软今晨面向快速通道的Insider会员推送Windows10新预览版,操作系统版本号Build19603。除了一些常规修复,本次更新还带了不少新功能,一起来了...

Android 16允许Linux终端使用手机全部存储空间

IT之家4月20日消息,谷歌Pixel手机正朝着成为强大便携式计算设备的目标迈进。2025年3月的更新中,Linux终端应用的推出为这一转变奠定了重要基础。该应用允许兼容的安卓设备...

Linux 系统管理大容量磁盘(2TB+)操作指南

对于容量超过2TB的磁盘,传统MBR分区表的32位寻址机制存在限制(最大支持2.2TB)。需采用GPT(GUIDPartitionTable)分区方案,其支持64位寻址,理论上限为9.4ZB(9....

Linux 服务器上查看磁盘类型的方法

方法1:使用lsblk命令lsblk输出说明:TYPE列显示设备类型,如disk(物理磁盘)、part(分区)、rom(只读存储)等。...

ESXI7虚机上的Ubuntu Linux 22.04 LVM空间扩容操作记录

本人在实际的使用中经常遇到Vmware上安装的Linux虚机的LVM扩容情况,最终实现lv的扩容,大多数情况因为虚机都是有备用或者可停机的情况,一般情况下通过添加一块物理盘再加入vg,然后扩容lv来实...

5.4K Star很容易!Windows读取Linux磁盘格式工具

[开源日记],分享10k+Star的优质开源项目...

Linux 文件系统监控:用脚本自动化磁盘空间管理

在Linux系统中,文件系统监控是一项非常重要的任务,它可以帮助我们及时发现磁盘空间不足的问题,避免因磁盘满而导致的系统服务不可用。通过编写脚本自动化磁盘空间管理,我们可以更加高效地处理这一问题。下面...

Linux磁盘管理LVM实战(linux实验磁盘管理)

LVM(逻辑卷管理器,LogicalVolumeManager)是一种在Linux系统中用于灵活管理磁盘空间的技术,通过将物理磁盘抽象为逻辑卷,实现动态调整存储容量、跨磁盘扩展等功能。本章节...

Linux查看文件大小:`ls`和`du`为何结果不同?一文讲透原理!

Linux查看文件大小:ls和du为何结果不同?一文讲透原理!在Linux运维中,查看文件大小是日常高频操作。但你是否遇到过以下困惑?...

使用 df 命令检查服务器磁盘满了,但用 du 命令发现实际小于磁盘容量

在Linux系统中,管理员或开发者经常会遇到一个令人困惑的问题:使用...

Linux磁盘爆满紧急救援指南:5步清理释放50GB+小白也能轻松搞定

“服务器卡死?网站崩溃?当Linux系统弹出‘Nospaceleft’的红色警报,别慌!本文手把手教你从‘删库到跑路’进阶为‘磁盘清理大师’,5个关键步骤+30条救命命令,快速释放磁盘空间,拯救你...

取消回复欢迎 发表评论: