Вопрос

Я только что получил Delphi 2009 и ранее прочитал несколько статей об изменениях, которые могут потребоваться из-за перехода на строки Unicode.В основном, упоминается, что sizeof(char) больше не гарантированно равен 1.Но почему это может быть интересно в отношении манипулирования строками?

Например, если я использую AnsiString:='Test' и делаю то же самое со строкой (которая теперь является unicode), то я получаю Length() = 4, что правильно для обоих случаев.Не тестируя это, я уверен, что все другие функции манипулирования строками ведут себя одинаково и внутренне решают, является ли аргумент строкой в юникоде или чем-то еще.

Почему фактический размер символа должен представлять для меня интерес, если я выполняю манипуляции со строками?(Конечно, если я использую strings как строки, а не для хранения каких-либо других данных)

Спасибо за любую помощь!Holger

Это было полезно?

Решение

С помощью Unicode Размер (SomeChar) <> Длина (некоторый размер).По существу, длина строка меньше суммы размеров его обугливающийсяs.До тех пор, пока вы не предполагаете SizeOf(символ) = 1, или SizeOf(someString[x]) = 1 (поскольку оба являются ЛОЖЬ сейчас) или попытайтесь поменять местами байты с обугливающийсясубъект, тогда у вас не должно возникнуть никаких проблем.В любом месте вы делаете что-то творческое . Байтs в Обугливающийсяы или Строкаs, тогда вам нужно будет использовать Регистрация.

(SizeOf(someString) по-прежнему равен 4, независимо от длины, поскольку по сути это указатель с некоторой магией компилятора.)

Другие советы

Люди часто неявно преобразуют символы в байты в старом коде Delphi, по-настоящему не задумываясь об этом.Например, при записи в поток.Когда вы записываете строку в поток, вы должны указать количество записываемых вами байт, но люди часто передают количество символов вместо этого.Видишь этот пост от Криса Бенсена приведу еще один пример.

Другим способом, которым люди часто выполняют это неявное преобразование и более старый код, является использование "строки" для хранения двоичных данных.В этом случае им на самом деле нужны байты, но тип данных ожидает символов.D2009 имеет лучший тип для этого.

Я не пробовал Delphi 2009, но использую fpc, который также медленно переходит на unicode.Я на 95% уверен, что все приведенное ниже справедливо и для Delphi 2009

В fpc (при поддержке unicode) это будет так, что такие функции, как 'length', учитывают кодовую страницу.Таким образом, он вернет длину строки такой, какой ее увидел бы "человек".Если есть, например, два китайских символа, которые оба занимают два байта памяти в юникоде, length вернет значение 2, поскольку в строке два символа.Но строка займет 4 байта памяти.(+ память для подсчета ссылок и начального # 0, но это в стороне)

Чего ты больше не можешь делать, так это этого:

var p : pchar;
begin
  p := s[1];
  for i := 0 to length(string)-1 do
    begin
    write(p);
    inc(p);
    end;      
end;

Потому что этот код - в примере с двумя китайскими символами - напишет неправильные два символа.А именно два байта, которые являются частью первого "реального" символа.

Короче говоря:Функция Length() возвращает больше не количество байт, выделенных для строки, а количество символов.(До перехода на unicode эти два значения были равны друг другу)

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

(Конечно, если я использую strings как строки, а не для хранения каких-либо других данных)

Это ключевой момент: вы не используете строки для других целей, но некоторые люди это делают.Они используют строки точно так же, как массивы, поэтому им (и мне в том числе) нужно было бы проверять все такие варианты использования, чтобы убедиться, что ничего не сломано...

Давайте не будем забывать, что бывают случаи, когда это преобразование на самом деле нежелательно.Скажем, для хранения GUID в записи, например.Идентификатор guid может содержать только шестнадцатеричные символы плюс скобки - и...если они будут занимать вдвое больше места, это может существенно повлиять на существующий код.Конечно, простое решение - изменить их на AnsiString и разобраться с предупреждениями компилятора, если вы выполняете какие-либо манипуляции со строками над ними.

Это может быть проблемой, если вы выполняете вызовы Windows API.Или, если у вас есть устаревший код, который делает инк или декабрь из str[0] чтобы изменить его длину.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top