在Delphi 2006中,如何从WideString中删除空字符?

4

我有一个WideString变量,其中包含一些数据,但是当字符串被分配时,一些额外的null被添加到数据的更多或更少随机的位置。现在我需要从变量中去掉这些null。如果它是一个字符串,我会检查每个Char,看看Char(x)= 0,但由于这是一个WideString,我不认为这样会起作用?如何最好地去除这些字符?

我正在使用Delphi 2006


2
术语说明:NULL(全大写,两个L)是C和C++宏,指代不指向任何地方的指针,也就是空指针NUL是ASCII字符索引为零的符号,也就是空字符。如果您在谈论指针,请只使用全大写的NULL;否则,将其像普通英语单词一样大写:“添加了一些额外的空字符”,“以空字符结尾的字符串”,“合同无效”。 - Rob Kennedy
感谢Rob。问题已相应更新。 - Marius
使用widestring时,您可以像使用ansi版本一样完全使用widechar。这也解决了其他人提出的关于零前导字节和零宽字符之间差异的问题。他们是正确的,如果将widestring中所有零字节剥离掉,那可能会很有趣但没有用处。 - Мסž
2个回答

9
你看到的可能不是空字符,而只是代码点值小于256的字符的前8位。
如果你确实在字符串中有不应该出现的空字符,首先要做的是找出它们是如何出现的。如果它们没有应该出现的地方,那么你的程序可能存在错误。
如果生成字符串的代码没有问题,但你仍然有不想要的空字符,那么你可以相对容易地将它们删除。通常使用Delete标准函数从字符串中删除内容。你可以使用#语法指定任何字符的数值,编译器通常可以确定它需要表示AnsiChar还是WideChar。
procedure RemoveNullCharacters(var s: WideString);
var
  i: Integer;
begin
  i := 1;
  while i < Length(s) do
    if s[i] = #0 then
      Delete(s, i, 1)
    else
      Inc(i);
end;

但是这样可能会多次重新分配字符串内存(每个空字符一次)。为了避免这种情况,您可以原地压缩字符串:

procedure RemoveNullCharacters(var s: WideString);
var
  i, j: Integer;
begin
  j := 0;
  for i := 1 to Length(s) do
    if s[i] <> #0 then begin
      Inc(j);
      s[j] := s[i];
    end;
  if j < Length(s) then
    SetLength(s, j);
end;

这些函数适用于 Delphi 的任何字符串类型;只需更改参数类型即可。


数据来自遗留系统,所以我没有任何办法解决潜在的问题... - Marius

6

这些并不是多余的空值,它们是字符串的一部分。

你应该阅读一些关于多字节字符的资料,其中包括WideStrings。字符的大小超过一个字节,其中一些额外的字节是NULLs。

你可以从Nick Hodges的Unicode文章开始阅读,这些文章是在Delphi 2009首次发布时编写的,旨在帮助人们从单字节字符过渡到多字节字符。我记得这个系列有三篇文章。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接