C ++: строка с несколькими языками

Это моя первая попытка разобраться в программе с несколькими языками. Я был бы очень признателен, если бы кто-нибудь мог предоставить мне учебный материал и способы решения этой проблемы.

Вопрос представляет собой строку на нескольких языках. Например, представьте себе строку, в которой на многих языках написано «Hello», разделенное запятыми. Я хочу разделить эти слова. Итак, мои вопросы:

  1. Могу ли я использовать для этого std :: string или мне следует использовать std :: wstring?
  2. Если я хочу токенизировать каждое из слов в строке и поместить их в char *, следует ли мне использовать wchar? Но некоторые кодировки, такие как UTF, могут быть больше, чем поддерживает wchar.
  3. В целом, каков «общепринятый» подход к этому типу дел?

Спасибо.


person madu    schedule 02.12.2013    source источник
comment
Взгляните на Gnu gettext, чтобы увидеть, как выполняется локализация.   -  person Paul Beckingham    schedule 02.12.2013


Ответы (1)


Могу ли я использовать для этого std::string или мне следует использовать std::wstring?

Оба могут использоваться. Если вы используете std::string, кодировка должна быть UTF-8, чтобы избежать нулевых байтов, которые вы получили бы, если бы использовали UTF-16, UCS-2 и т. Д. Если вы используете std::wstring, вы также можете использовать кодировки, требующие большие числа для представления отдельных символов, то есть UCS-2 и UCS-4, как правило, подходят, но, строго говоря, это зависит от реализации. В C ++ 11 также есть std::u16string (подходит для UTF-16 и UCS-2) и std::u32string (подходит для UCS-4).

Итак, какой из этих типов использовать, зависит от того, какую кодировку вы предпочитаете, а не от количества или типа языков, которые вы хотите представлять.

Как показывает опыт, UTF-8 отлично подходит для хранения больших текстов, тогда как UCS-4 лучше всего, если объем памяти не имеет большого значения, но вы хотите, чтобы итерации на уровне символов и арифметика положения были удобными и быстрыми. (Пример: пропуск n символов в строке UTF-8 - это операция O (n), тогда как в UCS-4 это операция O (1).)

Если я хочу токенизировать каждое из слов в строке и поместить их в char *, следует ли мне использовать wchar? Но некоторые кодировки, такие как UTF, могут быть больше, чем поддерживает wchar.

Я бы использовал для слов тот же тип данных, что и для самого текста. Т.е. слова из std::string текста также должны быть std::string, а слова из std::wstring должны быть std::wstring.

(Если действительно есть веская причина для перехода от строкового типа данных к типу данных символьного указателя, конечно, char* подходит для std::string, а wchar_t* подходит для std::string. Аналогично для типов C ++ 11 есть char16_t* и char32_t* .)

В целом, каков «общепринятый» подход к этому типу дел?

Первый вопрос, который вам нужно ответить самому себе, - какую кодировку вы хотите использовать для хранения и обработки. В международных условиях только кодировки Unicode действительно подходят, но есть еще больше, чем одна на выбор: UTF-8, UCS-2 и UCS-4 являются наиболее распространенными. Как описано выше, то, какой из них вы выберете, повлияет на объем памяти и скорость обработки, поэтому тщательно подумайте, какие типы операций вам необходимо выполнить. Может потребоваться преобразование из одной кодировки в другую в определенных точках вашей программы для оптимального пространственно-временного поведения. Как только вы узнаете, какую кодировку вы хотите использовать в каждой части программы, выберите соответствующий тип данных.

После выбора кодировки и типов данных вам также может потребоваться нормализация Unicode. Во многих языках один и тот же символ (или комбинация символов / диакритических знаков) может быть представлен более чем одной последовательностью кодовых точек Unicode (особенно при использовании комбинирования символов). Чтобы правильно справиться с этими случаями, вам может потребоваться применить нормализацию Unicode (например, NFKC) к строкам. Обратите внимание, что в стандартной библиотеке C ++ для этого нет встроенной поддержки.

person jogojapan    schedule 02.12.2013
comment
Большое спасибо за подробный ответ jogojapan. Хочу уточнить еще одну вещь. Как я могу указать, что моя строка закодирована в UTF-8? Например, на моем компьютере установлены японские иероглифы. Если я напишу программу на C ++, в которой есть как английские, так и японские строки символов, и использую для них std :: string, она будет работать на моей машине. Что, если я запустил ту же программу на другом компьютере. Как он узнает, что моя строка закодирована в UTF-8? Как я могу указать системе, что моя программа использует строки в кодировке UTF-8? Имеет ли смысл этот вопрос? - person madu; 02.12.2013
comment
Это зависит от того, как вы генерируете эти строки. Если строки являются частью вашей программы на C ++, они генерируются редактором (или IDE), который вы используете для создания своей программы. Где-то должна быть возможность выбрать, какую кодировку вы хотите использовать при сохранении файла. Если вы не можете этого узнать, вы можете попробовать загрузить файл в другом редакторе (или в веб-браузере), который позволяет вам выбрать кодировку отображения. Если вы выбрали UTF-8, а затем не можете прочитать символ, вы знаете, что файл был сохранен в другой кодировке. - person jogojapan; 02.12.2013
comment
Спасибо jogojapan. Итак, кажется, что если я использую кодировку UTF-8, а другие системы, которые будут использовать эту программу, также имеют поддержку UTF-8, мне не нужно выполнять какую-либо специальную обработку, чтобы иметь строку с несколькими языками? Но когда я пишу программу, предположим, что моя IDE использует кодировку UTF-8, но что произойдет, если мой исполняемый файл будет запущен на другом компьютере? Например, если я создаю эту программу как EXE-файл консоли Win32, а затем запускаю ее на другом компьютере WIndows, как эта машина узнает, что нужно интерпретировать строки как UTF-8? Эта информация не включена в исполняемый файл, не так ли? Спасибо. - person madu; 02.12.2013
comment
Если строки являются частью программы (т.е. если они определены как литералы, например, если у вас есть код типа std::string s = "文字列"; в вашем коде), то строки также будут частью исполняемого файла. У них будет одинаковая кодировка на каждой машине, на которой вы ее запускаете. - person jogojapan; 02.12.2013
comment
У вас могут возникнуть проблемы, когда вы компилируете свой код на другой платформе. Компилятор может отклонить строки в кодировке UTF-8 в вашем коде. В этом случае лучше всего сохранить строки в отдельном файле и загрузить этот файл из вашего кода. Тогда вы можете быть уверены, что кодировка будет одинаковой на всех платформах. - person jogojapan; 02.12.2013
comment
Большое спасибо jogojapan. Теперь все довольно ясно. Просто немного запутался в том, как у исполняемого файла не будет проблем с кодировкой. Я представил, что система должна знать, какая кодировка использовалась во время компиляции, чтобы декодировать строку (и правильно отображать ее на консоли). Ценю вашу помощь! - person madu; 02.12.2013
comment
Если у вас есть такая программа, как std::cout << "文字" << std::endl;, то компилятор скомпилирует байтовую последовательность 文字 в программу. Если вы перенесете это на другой компьютер и выполните его там, там будет создана точно такая же последовательность байтов (такая же кодировка). Если консоль там не поддерживает UTF-8 или не имеет правильного шрифта или чего-то еще, тогда строка будет отображаться неправильно. Ни ОС, ни консоль не будут пытаться угадать кодировку, декодировать ее во что-то еще и затем вывести. - person jogojapan; 02.12.2013
comment
Спасибо! Вот что сбивало с толку. - person madu; 02.12.2013