2016-05-23 4 views
2

Я ищу способ преобразования wstring в простой string, содержащий только символы ASCII. Любой символ, отсутствующий в ASCII (0-127), должен быть преобразован в ближайший символ ASCII. Если нет аналогичного символа ASCII, символ следует опустить.Как преобразовать широкую строку в ASCII

Чтобы проиллюстрировать это, давайте рассмотрим следующую строку широких:

wstring text(L"A naïve man called 晨 was having piña colada and crème brûlée."); 

Преобразованный вариант Я ищу это (уведомление об отсутствии диакритики):

string("A naive man called was having pina colada and creme brulee.") 

Edit:

Относительно цели : Я пишу приложение, которое анализирует Английские тексты. Входными файлами являются UTF-8 и могут содержать специальные символы. Часть моего приложения использует библиотеку, написанную на языке C, которая понимает только ASCII. Поэтому мне нужен способ «потушить» текст в ASCII, не теряя слишком много информации.

Что касается точных требований: Любой символ, являющийся диакритической версией символа ASCII, должен быть преобразован в этот символ ASCII; все остальные символы должны быть опущены. Таким образом, ı, ĩ и î должны стать i, потому что это все версии небольшой латинской буквы i. Символ ɩ (iota), с другой стороны, визуально подобный, не является версией маленькой латинской буквы i и поэтому должен быть опущен.

+1

* «Любой символ, отсутствующий в ASCII (0-127), должен быть преобразован в ближайший символ ASCII. Если нет аналогичного символа ASCII, символ должен быть опущен». * Это не звучит четко вообще. Является ли почти t? –

+2

Вам просто нужно определить «похожие» и «самые близкие». Может быть, огромный стол? –

+0

С какой целью? –

ответ

4

На GitHub, есть unidecode-cxx, который является (несколько незавершенной) C++ порт node-unidecode, который в свою очередь, порт JavaScript из в Perl Text::Unicode.C++ версия немного грубо по краям, но пример в src/unidecode.cxx может быть изменен, чтобы преобразовать пример строки,

A naïve man called 晨 was having piña colada and crème brûlée.

следующим образом:

A naive man called Chen was having pina colada and creme brulee.

Для того, чтобы получить код для компиляции без Gyp (что-то я нев эр используется и не было времени, чтобы выяснить только сейчас), я должен был изменить код несколько (быстрая и грязная):

  • Добавить #include <iostream> в src/unidecode.cxx, и добавьте следующие main рутина:

    int main() { 
        string output_buf; 
        string input_buf = "A naïve man called 晨 was having piña colada and crème brûlée."; 
        unidecode(&input_buf, &output_buf); 
        cout << output_buf.c_str() << endl; 
    } 
    
  • Заменить все упоминания о NULL в src/data.cxx с nullptr

Затем я составил

g++ -std=c++11 -o unidecode unidecode.cxx 

для получения желаемого результата.

Код выглядит как довольно примитивный порт и может иметь некоторые улучшения, особенно в более «правильные» C++. Он внутренне использует статически скомпилированную таблицу преобразований, которая, вероятно, может быть адаптирована в соответствии с вашими потребностями, если это не так.

0

wstring является string из wchar, который является символом, который может иметь размер 2 или 4 байта. Между тем UTF8 представляет собой кодировку с переменной длиной с размером символа 1-4 байта. Таким образом, ваш запрос не полностью согласован.

Предполагая, что вы выяснили, как именно данные хранятся в ваших строках, я предлагаю вам проверить библиотеку ICU, чтобы сделать дальнейшие преобразования.

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

Решение mindriot более кратким, но все же вам необходимо преобразовать wstring в правильную последовательность UTF8.