Вопрос

Есть ли в Delphi 2007 процедура для преобразования символов в верхнем диапазоне таблицы ANSI (> 127) в их эквивалентные символы в чистом ASCII (<= 127) в соответствии с языковым стандартом (кодовой страницей)?

Я знаю, что некоторые символы не могут быть хорошо переведены, но большинство может, особенно.в диапазоне 192-255:

  • ÀА
  • àа
  • ËЭ
  • ëе
  • ÇС
  • çс
  • (тире)- (дефис – это может быть сложнее)
  • (эм тире)- (дефис)
Это было полезно?

Решение

WideCharToMultiByte выполняет наилучшее сопоставление для любых символов, которые не поддерживаются указанным набором символов, включая удаление диакритических знаков.Вы можете делать именно то, что хотите, используя это и передав 20127 (US-ASCII) в качестве кодовой страницы.

function BestFit(const AInput: AnsiString): AnsiString;
const
  CodePage = 20127; //20127 = us-ascii
var
  WS: WideString;
begin
  WS := WideString(AInput);
  SetLength(Result, WideCharToMultiByte(CodePage, 0, PWideChar(WS),
    Length(WS), nil, 0, nil, nil));
  WideCharToMultiByte(CodePage, 0, PWideChar(WS), Length(WS),
    PAnsiChar(Result), Length(Result), nil, nil);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
   ShowMessage(BestFit('aÀàËëÇç–—€¢Š'));
end;

Вызов этого с вашими примерами дает результаты, которые вы ищете, включая случай с тире в минус, который, я не думаю, обрабатывается предложением Джеруна о преобразовании в форму нормализации D.Если вы действительно хотите использовать этот подход, у Майкла Каплана есть Сообщение блога в нем явно обсуждается удаление диакритических знаков (а не нормализация в целом), но используется C# и API, представленный в Vista.Вы можете получить нечто подобное, используя API FoldString (любая версия WinNT).

Конечно, если вы делаете это только для одного набора символов и хотите избежать накладных расходов на преобразование в WideString и обратно, Паду прав, что простой цикл for и таблица поиска будут столь же эффективны.

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

Просто чтобы расширить ответ Крейга для Delphi 2009:

Если вы используете Delphi 2009 и новее, вы можете использовать более читаемый код с тем же результатом:

function OStripAccents(const aStr: String): String;
type
  USASCIIString = type AnsiString(20127);//20127 = us ascii
begin
  Result := String(USASCIIString(aStr));
end;

К сожалению, этот код работает только в MS Windows.На Mac акценты заменяются не наиболее подходящими символами, а вопросительными знаками.

Очевидно, что Delphi внутри Windows использует WideCharToMultiByte, тогда как на Mac используется iconv (см. LocaleCharsFromUnicode в System.pas).Вопрос в том, следует ли рассматривать это различное поведение в разных ОС как ошибку и сообщать об этом в CodeCentral.

Я считаю, что лучше всего создать таблицу поиска.

То, что вы ищете, это нормализация.

Майкл Каплан написал хорошая статья в блоге о нормализации.

Это не решит вашу проблему сразу, но укажет вам правильное направление.

--джероен

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