Как узнать код символа для персонажа 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