Arrays 发送字符数组中的†字符而不是空格字符
我已将我的项目从XE5迁移到西雅图10。我仍在使用ANSII代码与设备通信。在我的新版本中,西雅图IDE发送的是†字符,而不是字符数组中Ansii代码中32的空格字符。我需要将空格字符数据发送到文本文件,但我不能 我试过32,就像我以前用过的一样,032和127,但都不起作用。有什么想法吗 以下是我如何使用:Arrays 发送字符数组中的†字符而不是空格字符,arrays,delphi,char,pascal,delphi-10-seattle,Arrays,Delphi,Char,Pascal,Delphi 10 Seattle,我已将我的项目从XE5迁移到西雅图10。我仍在使用ANSII代码与设备通信。在我的新版本中,西雅图IDE发送的是†字符,而不是字符数组中Ansii代码中32的空格字符。我需要将空格字符数据发送到文本文件,但我不能 我试过32,就像我以前用过的一样,032和127,但都不起作用。有什么想法吗 以下是我如何使用: fillChar(X,50,#32); 方法签名var-X;计数:整数;Value:Ordinal如果要使用ANSI与设备通信,可以将数组定义为 x: array[1..50] of A
fillChar(X,50,#32);
方法签名var-X;计数:整数;Value:Ordinal如果要使用ANSI与设备通信,可以将数组定义为
x: array[1..50] of AnsiChar;
在本例中,使用您使用的空格字符填充它
FillChar(x, 50, #32);
在Unicode环境中,使用AnsiChar数组作为通信缓冲区可能会很麻烦,因此我建议使用字节数组作为通信缓冲区
x: array[1..50] of byte;
并将其初始化为
FillChar(x, 50, 32);
尽管名称不同,FillChar填充的是字节,而不是字符
Char是Delphi 2009+中WideChar 2字节的别名,在以前的版本中,它是AnsiChar 1字节的别名
因此,如果您有一个由WideChar元素组成的50个元素的数组,那么该数组的大小是100字节。当您调用fillCharX,50,32时,它将填充前50个字节,每个字节的值为$20。因此,前25个WideChar元素的值为$2020,又称Unicode codepoint U+2020 DAGGER,†,而后25个元素的值没有任何意义
该问题在以下章节中进行了解释:
用指定值填充连续字节
在Delphi中,FillChar使用value value指定的值填充X引用的Count连续字节,value可以是Byte或AnsiChar类型
请注意,如果X是一个UnicodeString,这可能不会像预期的那样工作,因为FillChar需要一个字节计数,它与字符计数不同
此外,填充字符是单字节字符。因此,当Buf是一个单链分解时,代码FillCharBuf,LengthBuf,9;用代码点$0909而不是$09填充Buf。在这种情况下,应该使用StringOfChar例程
Embarcadero的白皮书中也解释了这一点,例如Cary Jensen的第28页:
实际上,这类代码的复杂性与指针和缓冲区本身无关。问题是由于字符被用作指针。因此,现在字符串和字符的大小(以字节为单位)发生了变化,这段代码所包含的一个基本假设不再有效:单个字符的长度为一个字节
由于这种类型的代码在Unicode转换和维护方面存在很大的问题,需要进行详细的检查,因此可以在可能的情况下对这种代码进行重构。简而言之,从这些操作中删除Char类型,然后切换到另一种更合适的数据类型。例如,Olaf Monien写道,我不建议对字符或字符串类型使用面向字节的操作。如果需要字节缓冲区,则使用“byte”作为byte;的[数据类型:buffer:array[0..255]
例如,过去您可能做过类似的事情:
var
Buffer: array[0..255] of AnsiChar;
begin
FillChar(Buffer, Length(Buffer), 0);
如果您只想转换为Unicode,可以进行以下更改:
var
Buffer: array[0..255] of Char;
begin
FillChar(Buffer, Length(buffer) * SizeOf(Char), 0);
另一方面,可以提出一个很好的理由,放弃使用Char数组作为缓冲区,并切换到Byte数组,正如Olaf所建议的那样。由于缓冲区的大小,这可能与第一段类似,但与第二段不同:
var
Buffer: array[0..255] of Byte;
begin
FillChar(Buffer, Length(buffer), 0);
更好的方法是,使用第二个参数FillChar,无论数组的数据类型如何,它都可以工作:
var
Buffer: array[0..255] of Byte;
begin
FillChar(Buffer, Length(buffer) * SizeOf(Buffer[0]), 0);
最后两个示例的优点是,您首先拥有了真正想要的东西,一个可以保存字节大小值的缓冲区。Delphi不会尝试应用任何形式的隐式字符串转换,因为它使用的是字节而不是代码单位。如果你想做指针数学,你可以用PByte。PByte是指向字节的指针
当您与需要指向字符或字符数组的指针的外部库交互时,可能无法进行类似的更改。在这些情况下,它们实际上是在请求一个字符缓冲区,而这些通常是AnsiChar类型
因此,为了解决您的问题,因为您正在与需要Ansi数据的外部设备交互,所以需要将数组声明为使用AnsiChar或Byte元素,而不是WideChar元素。然后您原来的FillChar调用将再次正常工作。什么类型的“X”?西雅图不是“发送”,你的代码是。什么代码?X:Char的数组[1..50];所以你用$2020个字符填充数组的一半。在XE5中也是如此。你知道字符在两个版本中都是Unicode吗?@MBo是的,我在旧版本中使用过。XE5、Turbo Delphi等等。@TomBrunberg我要试试这个解决方案。问题几乎是一样的。谢谢@RudyVelthuis纠正我的打字错误,否则我想你会复制粘贴的, 正当因为你有两次同样的打字错误。