在 Char 数组中发送 † 字符而不是 Space 字符

Sending † character instead of Space character in Char array

我已将我的项目从 XE5 迁移到 10 Seattle。我仍在使用 ANSII 代码与设备通信。在我的新版本中,Seattle IDE 在 Char 数组中发送 † 字符而不是 space 字符(在 Ansii 代码中为 #32)。我需要将 space 字符数据发送到文本文件,但我不能。

我尝试了#32(就像我之前使用的那样)、#032 和#127,但它们不起作用。有什么想法吗?

我是这样使用的:

fillChar(X,50,#32);

方法签名 (var X; count:Integer; Value:Ordinal)

如果您想使用 ANSI 与设备通信,您可以将数组定义为

x: array[1..50] of AnsiChar;

在这种情况下,用 space 个您使用的字符填充它

FillChar(x, 50, #32);

在 Unicode 环境下使用 AnsiChar 数组作为通信缓冲区可能会很麻烦,因此我建议使用 byte 数组作为通信缓冲区

x: array[1..50] of byte;

并用

初始化
FillChar(x, 50, 32);

尽管它的名称,FillChar() 填充 字节 ,而不是 个字符

CharWideChar(2 字节)在 Delphi 2009+ 中的别名,在以前的版本中它是 AnsiChar(1 字节)的别名.

因此,如果您有一个包含 WideChar 个元素的 50 元素数组,则该数组的大小为 100 字节。当您调用 fillChar(X,50,#32) 时,它会在前 50 个 字节 中填充每个值 </code>。因此,前 25 个 <code>WideChar 元素的值为 20(也称为 Unicode 代码点 U+2020 DAGGER),后 25 个元素将没有任何有意义的值。

这个问题在 FillChar() documentation:

Fills contiguous bytes with a specified value.

In Delphi, FillChar fills Count contiguous bytes (referenced by X) with the value specified by Value (Value can be of type Byte or AnsiChar)

Note that if X is a UnicodeString, this may not work as expected, because FillChar expects a byte count, which is not the same as the character count.

In addition, the filling character is a single-byte character. Therefore, when Buf is a UnicodeString, the code FillChar(Buf, Length(Buf), #9); fills Buf with the code point 09, not . In such cases, you should use the StringOfChar routine.

Cary Jensen 在 Embarcadero 的 Unicode Migration Resources white papers, for instance on page 28 of Delphi Unicode Migration for Mere Mortals: Stories and Advice from the Front Lines 中也对此进行了解释:

Actually, the complexity of this type of code is not related to pointers and buffers per se. The problem is due to Chars being used as pointers. So, now that the size of Strings and Chars in bytes has changed, one of the fundamental assumptions that much of this code embraces is no longer valid: That individual Chars are one byte in length.

Since this type of code is so problematic for Unicode conversion (and maintenance in general), and will require detailed examination, a good argument can be made for refactoring this code where possible. In short, remove the Char types from these operations, and switch to another, more appropriate data type. For example, Olaf Monien wrote, "I wouldn't recommend using byte oriented operations on Char (or String) types. If you need a byte-buffer, then use ‘Byte’ as [the] data type: buffer: array[0..255] of Byte;."

For example, in the past you might have done something like this:

var
  Buffer: array[0..255] of AnsiChar;
begin
  FillChar(Buffer, Length(Buffer), 0);

If you merely want to convert to Unicode, you might make the following changes:

var
  Buffer: array[0..255] of Char;
begin
  FillChar(Buffer, Length(buffer) * SizeOf(Char), 0);

On the other hand, a good argument could be made for dropping the use of an array of Char as your buffer, and switch to an array of Byte, as Olaf suggests. This may look like this (which is similar to the first segment, but not identical to the second, due to the size of the buffer):

var
  Buffer: array[0..255] of Byte;
begin
  FillChar(Buffer, Length(buffer), 0);

Better yet, use this second argument to FillChar which works regardless of the data type of the array:

var
  Buffer: array[0..255] of Byte;
begin
  FillChar(Buffer, Length(buffer) * SizeOf(Buffer[0]), 0);

The advantage of these last two examples is that you have what you really wanted in the first place, a buffer that can hold byte-sized values. (And Delphi will not try to apply any form of implicit string conversion since it's working with bytes and not code units.) And, if you want to do pointer math, you can use PByte. PByte is a pointer to a Byte.

The one place where changes like may not be possible is when you are interfacing with an external library that expects a pointer to a character or character array. In those cases, they really are asking for a buffer of characters, and these are normally AnsiChar types.

因此,为了解决您的问题,由于您正在与需要 Ansi 数据的外部设备进行交互,因此您需要将数组声明为使用 AnsiCharByte 元素而不是 (Wide)Char 元素。然后您原来的 FillChar() 调用将再次正常工作。