Индексный символ вместо байта в строке Delphi

Я читаю документ по индексу для строки Delphi, как показано ниже:

http://docwiki.embarcadero.com/RADStudio/Tokyo/en/String_Types_(Delphi)

В одном заявлении говорилось:

Вы можете индексировать строковую переменную так же, как массив. Если S - строковая переменная, отличная от UnicodeString, а i - целочисленное выражение, S [i] представляет i-й байт в S, который может вообще не быть i-м символом или целым символом для многобайтовой символьной строки (MBCS). Точно так же индексирование переменной UnicodeString приводит к тому, что элемент может не быть полным символом. Если строка содержит символы в Basic Multilingual Plane (BMP), все символы имеют размер 2 байта, поэтому при индексации строки появляются символы. Однако, если некоторые символы отсутствуют в BMP, индексированный элемент может быть суррогатной парой, а не целым символом.

Если я правильно понял, S[i] является индексом i-го байта строки. Если S - это UnicodeString, то S[1] - это первый байт, S[2] - второй байт первого символа, S[3] - первый байт второго символа и т. Д. Если это так, то как мне индексировать символ вместо байт внутри строки? Мне нужно индексировать символы, а не байты.


person alancc    schedule 24.10.2018    source источник
comment
Нет, символ Unicode в Delphi составляет два байта, и если S является string (= UnicodeString в Delphi 2009 или новее), S[i] является таким двухбайтовым символом. Но только символы Unicode в BMP могут быть представлены в виде двухбайтовых единиц, поэтому S[i] действительно может быть только одной из двух частей в суррогатной паре.   -  person Andreas Rejbrand    schedule 24.10.2018
comment
(В подавляющем большинстве всех приложений вам нужен только BMP. Он содержит десятки тысяч символов. Однако я не знаю ваше приложение.)   -  person Andreas Rejbrand    schedule 24.10.2018
comment
Итак, в простой строке, такой как Test ∫⌬dx ᚭᛘᚠ ቚ ꡵ 씒 ᱶⵞꮙ ៚ ㆯ, S[i] - это полный символ.   -  person Andreas Rejbrand    schedule 24.10.2018
comment
Пожалуйста, добавляя теги, добавляйте правильный. Не помечайте delphi-xe2, а delphi-xe3, поскольку вы фактически используете Delphi XE3.   -  person Tom Brunberg    schedule 24.10.2018
comment
Вы цитируете это предложение: Если S не является строкой UnicodeString ..., S [i] представляет i-й байт в S, .... Позже вы сделаете вывод: Если S - это строка Unicode, то S [1] - это первый байт, S [2] - это второй байт первого символа, .... Вы видите противоречие между этими двумя предложениями?   -  person Tom Brunberg    schedule 24.10.2018
comment
@TomBrunberg, Спасибо за объяснение. Что касается тега, когда я ввожу delphi, я получаю delphi-xe2, delphi и т.д., но не delphi-xe3, поэтому я думаю, что delphi-xe3 - новый тег, и моей репутации недостаточно, чтобы создать новый.   -  person alancc    schedule 25.10.2018
comment
@TomBrunberg Тогда, если S не является строкой MBCS в Юникоде, как индексировать символ вместо байта?   -  person alancc    schedule 25.10.2018
comment
Re. тег delphi-xe3, вам когда-нибудь приходило в голову набирать больше символов, пока вы не получите правильный выбор или даже не весь тег? Ваша репутация не имеет ничего общего с тем, какие теги отображаются, и вам не нужно создавать новые, поскольку все теги delphi уже существуют.   -  person Tom Brunberg    schedule 26.10.2018


Ответы (1)


В Delphi S[i] - это char или widechar. Но это не «символ» Unicode, это значение в кодировке UTF-16 в 16 битах (2 байта). В прошлом веке, то есть до 1996 года, Unicode был 16-битным, но теперь это не так! Внимательно прочтите FAQ по Unicode.

Вам может понадобиться несколько widechar, чтобы иметь полную кодовую точку Unicode = более или менее то, что мы обычно называем «символом». И даже это может быть неправильно, если используются диакритические знаки.

UTF-16 использует одну 16-битную кодовую единицу для кодирования наиболее распространенных 63K символов и пару 16-битных кодовых единиц, называемых суррогатами, для кодирования 1M менее часто используемых символов в Unicode.

Первоначально Unicode был разработан как чистая 16-битная кодировка, предназначенная для представления всех современных скриптов. (Древние письменности должны были быть представлены персонажами частного использования.)

Со временем, особенно после добавления более 14 500 составных символов для совместимости с устаревшими наборами, стало ясно, что для сообщества пользователей 16-битных символов недостаточно. Из этого возник UTF-16.

см. Часто задаваемые вопросы по UTF-16

Для правильного декодирования кодовых точек Unicode в Delphi см. Обнаружение и получение кодовых точек и суррогатов из строки Delphi (ссылка @LURD в Комментарии)

person Arnaud Bouchez    schedule 24.10.2018