Я обнаружил интересную проблему при обработке строк UTF-8, содержащих символы, отличные от ASCII, с помощью функций форматирования стандартной библиотеки C, таких как sprintf():
Функции семейства printf() не знают о utf-8 и обрабатывают все на основе количества байтов, а не символов. Поэтому форматирование неверное.
Простой пример:
#include <stdio.h>
int main(int argc, char *argv[])
{
const char* testMsg = "Tääääßt";
char buf[1024];
int len;
sprintf(buf, "|%7.7s|", testMsg);
len = strlen(buf);
printf("Result=\"%s\", len=%d", buf, len);
return 0;
}
Результат:
Result="|Täää|", len=7
Скорее всего, некоторые из вас порекомендуют преобразовать приложение из char в wchar_t и использовать fwprintf() и т. д., но это абсолютно невозможно из-за огромного количества существующих приложений. Я мог бы представить себе написание оболочки, которая использует эти функции внутри, но это было бы сложно и очень неэффективно.
Таким образом, лучшим решением будет замена функций форматирования стандартной библиотеки C с поддержкой UTF-8.
В настоящее время я работаю над QNX 6.4, но отвечаю за другие операционные системы. например Linux, также очень приветствуются.
printf
количество байтов для строки Unicode? - person trojanfoe   schedule 17.02.2012fwprintf
в любом случае не подходит для усечения данных Unicode — например, вы можете вырезать снять ударение, не обрезая символ, к которому он относится. Поэтому, что бы вы ни использовали, убедитесь, что значение длины, которую вы указываете, вам понятно. - person Steve Jessop   schedule 17.02.2012len()
, однозначно возвращают количество байтов (или, ну, элементов). Тот факт, что они отображаются как разное количество символов в вашей локали, в основном не контролируется C. Если вам нужна ширина отображения, не используйте функцию для подсчета байтов. - person tripleee   schedule 17.02.2012utf8strlen
измеряет количество кодовых точек. Итак, как отмечает Дитрих, если вы обрежете строку, которая выглядит как"Tä"
, до 2 символов, вы получитеTa
, если исходная строка была U+0054 U+0061 U+0308. - person Steve Jessop   schedule 17.02.2012