iconv - сохранение символов, которые нельзя преобразовать в ascii

Я использую функцию транслитерации iconv для преобразования строки Unicode в ближайший эквивалент ASCII. Однако строка содержит некоторые символы, не имеющие эквивалента в ASCII. Я хочу сохранить такие символы, не удаляя их.

В настоящее время вот что я делаю:

iconv_t cd = iconv_open("ASCII//IGNORE//TRANSLIT", "UTF-8");
const char *utf8 = "ç ß ∑ a";

char* in = const_cast<char*>(utf8);
size_t in_bytes = strlen(in);

char buf[BUFSIZ] = {};
char* out = buf;
size_t out_bytes = sizeof(buf);

iconv(cd, &in, &in_bytes, &out, &out_bytes);

printf("%s", buf);

// prints 
c ss  a

Как мне настроить iconv для получения вывода, подобного следующему:

c ss ∑

Если это невозможно с iconv, есть ли способ добиться этого программно в противном случае?


person jeffreyveon    schedule 02.10.2019    source источник
comment
Из документа: Функция iconv преобразует один многобайтовый символ за раз   -  person stark    schedule 02.10.2019
comment
Хотя это кажется таким странным :D Для чего вы собираетесь использовать эту интересную функцию?   -  person Ry-♦    schedule 02.10.2019
comment
Ну, во-первых, команда, которую вы разместили, не производит этот вывод на моей машине, а выдает ошибку (может быть, удалить //IGNORE?). Во-вторых, iconv — это просто простая утилита командной строки, в программе на C вы должны иметь возможность просто попытаться перевести каждую кодовую точку Unicode отдельно и увидеть результат. Что вы написали, что не работает? Вы должны добавить соответствующий код C.   -  person Marco Bonelli    schedule 02.10.2019
comment
Я добавил фактический код.   -  person jeffreyveon    schedule 02.10.2019


Ответы (1)


iconv не поддерживает поведение при преобразовании, которое вы хотите видеть «из коробки», потому что это довольно странное поведение: если это нормально иметь ∑ на выходе, почему бы не иметь ß на выходе? выход?

В любом случае, вы можете реализовать это преобразование с помощью собственной функции, использующей iconv, следующим образом:

  1. Выделите два дескриптора конверсии:
    iconv_t cd0 = iconv_open("UTF-8", "UTF-8");
    iconv_t cd1 = iconv_open("ASCII//TRANSLIT", "UTF-8");
    
  2. Используйте цикл, который повторно преобразует часть строки через iconv() с cd1. Когда вызов завершается с ошибкой errno == EILSEQ, вы знаете, что это происходит из-за символа, который не может быть транслитерирован в ASCII.
  3. В этот момент используйте вызов iconv() с cd0 для преобразования одного и только одного символа. Вы делаете это, вызывая iconv() с in = 1, затем, если это не удается, с in = 2, и так далее до in = 4. один входной байт и оставить один '?' на выходе.)
  4. После неоперативного преобразования одного символа вернитесь к шагу 2.
person Bruno Haible    schedule 02.10.2019