【问题标题】:How to find out char code for a character of an Ansistring如何找出 Ansistring 字符的字符代码
【发布时间】:2016-08-05 05:14:21
【问题描述】:

在旧版本的 Delphi 中,如 D7,您可以像 ord(s[i]) 那样做,其中 s 是一个字符串,但尝试使用 AnsiString 会导致异常(访问冲突)。

附:我很长一段时间都在使用 delphi 7。

以下是重现错误的步骤: 创建一个新项目并通过表单上的备忘录(让它成为 memo1)而不是将以下代码添加到表单创建事件处理程序:

procedure TForm1.FormCreate(Sender: TObject);
var u: ansistring;
begin
    u := 'stringtest';
    memo1.Lines.Add(inttostr(ord(u[2])));
end;

对我来说,这段代码会产生一个 AV。

【问题讨论】:

  • string 在 D7 AnsiString。在较新版本中索引到 AnsiString 的行为没有改变。
  • 这完全是不真实的。如果是这种情况,您的代码有问题,但显然没有您的代码,我们无法告诉您问题可能是什么。
  • 我不明白为什么无法显示生成 AV 的代码。您是否害怕有人窃取您宝贵的思想成果以及其中包含的所有错误?
  • @Tom Brunberg 这是可能的,我已将代码添加到问题中。我想我应该首先这样做,请原谅我没有这样做。

标签: delphi char ansistring


【解决方案1】:

它可以与 ansistring 一起使用,但你不能读到它的末尾并且你必须确保字符串已经初始化。

function CharCode(const S: ansistring; pos: integer): byte;
begin
  if pos <= 0 then result:= 0
  //else if s='' then Result:= 0 //unassigned string;
  else if Length(s) < Pos then Result:= 0  //cannot read past the end.
  else Result:= Ord(s[pos]);
end;

注意if s='' 与询问if pointer(s) = nil 相同。空字符串实际上是一个 nil 指针。
这可能就是您遇到访问冲突的原因。

如果你想强制 ansistring 为一定长度,你可以使用SetLength(MyAnsistring, NewLength);

(ansi) 字符串的长度是可变的。这意味着它会根据需要增长和缩小。如果您阅读超出字符串末尾的内容,您可能会遇到访问冲突。
请注意,您没有必须来获得 AV,RTL 在其分配方面留下了一些松弛;它通常分配比请求稍大的缓冲区,这是由于性能和架构原因。

如果读取到字符串的末尾,您可能无法获得 AV 的另一个原因是您的程序可能同时拥有字符串缓冲区 任何恰好在它旁边的内容。

因此,在调试模式{$R+} 中启用范围检查是个好主意,它会添加额外的检查以防止读取超出结构的末尾。

短字符串和(ansi)字符串的区别
短字符串具有固定长度,并且存在于堆栈中。
长字符串(ansi 或宽)是指向在堆上分配的记录的指针;它看起来像这样:

type
  TStringRecord = record
    CodePage: word;     
    ElementSize: word; //(1, 2 or 4)    
    ReferenceCount: integer;    
    Length: Integer;    
    StringData: array[1..length(s)] of char;
    NullChar: char;
  end;

编译器会对您隐藏所有这些细节。
见:http://docwiki.embarcadero.com/RADStudio/Seattle/en/Internal_Data_Formats

【讨论】:

  • 这很奇怪,但不起作用:u := ansistring('string');memo1.Lines.Add(inttostr(charcode(u,3))); 其中 u 被声明为 ansistring。
  • 原因不太可能与范围有关,因为在上面的示例中,我并没有试图读到结尾或接近它。
  • @Gonzalez:定义“不起作用”,因为该示例不可能在调用 CharCode()IntToStr() 时与 AV 一起崩溃。一个 AV 必须改为呼叫memo1.Lines.Add()。引发的错误消息的确切文本是什么?
  • @Gonzalez,它在我的机器上运行正常。这运行得很好:program Project76; {$APPTYPE CONSOLE} uses System.SysUtils; function CharCode(const S: ansistring; pos: integer): byte; begin if s='' then Result:= 0 //unassigned string; else if Length(s) &lt; Pos then Result:= 0 //cannot read past the end. else Result:= Ord(s[pos]); end; var u: ansistring; begin u:= ansistring('string'); writeln(IntToStr(CharCode(u,3))); ReadLn; end.
  • @Johan:如果您之后检查Length(),则无需检查if s='' then。空白/nil 字符串的Length() 为0,因此将由if Length(s) &lt; Pos then 检查处理。不过,您可能希望将语句更改为 if (Pos &lt; 1) or (Pos &gt; Length(s)) then
猜你喜欢
  • 2015-01-08
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-29
相关资源
最近更新 更多