Как узнать код символа для персонажа Ansistring

В старых версиях Delphi, таких как D7, вы могли делать ord(s[i]) где s была строка, но попытка этого с AnsiString приводит к исключению (нарушение доступа).

PS Я долгое время был w/delphi 7.

Вот шаги для воспроизведения ошибки: Создайте новый проект и с помощью памятки в форме (пусть это будет memo1), затем добавьте следующий код в обработчик события создания формы:

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

Для меня этот код производит AV.

1 ответ

Он работает с ANISTRIST, но вы не можете прочитать его до конца, и вы должны убедиться, что строка инициализирована.

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, Пустая строка действительно нулевой указатель.
Это, вероятно, почему вы получили нарушение доступа.

Если вы хотите, чтобы ANISTRING была определенной длины, вы можете использовать SetLength(MyAnsistring, NewLength);

Длина строки (ansi) является переменной. Это означает, что он растет и сжимается по мере необходимости. Если вы прочитаете за концом строки, вы можете получить нарушение прав доступа.
Обратите внимание, что вам не нужно получать AV, RTL немного ослабляет его распределение; обычно он выделяет немного больший буфер, чем запрошено, это связано с производительностью и архитектурными соображениями.

Другая причина, по которой вы можете не получить AV, читая после конца строки, состоит в том, что ваша программа может владеть как строковым буфером, так и любым другим, находящимся рядом с ним.

По этой причине рекомендуется включить проверку диапазона в режиме отладки. {$R+} это добавляет дополнительные проверки, чтобы защитить от чтения после конца структур.

Разница между короткой строкой и (ansi) строкой
Короткая строка имеет фиксированную длину и находится в стеке.
Длинная строка (ansi или wide) - указатель на запись, которая выделяется в куче; это выглядит так:

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

Другие вопросы по тегам