Как использовать Unicode в C++?

Принятие очень простой программы, что:

  • спросите имя.
  • сохраните имя в переменной.
  • отобразите переменное содержание на экране.

Это настолько просто, который первая вещь, которую каждый изучает.

Но моя проблема состоит в том, что я не знаю, как сделать то же самое, если я ввожу имя с помощью японских символов.

Так, если Вы знаете, как сделать это в C++, покажите мне пример (что я могу скомпилировать и протестировать),

Спасибо.


user362981:Спасибо за помощь. я скомпилировал код, который Вы написали без проблемы, их, консоль появляется, и я не могу ввести японские символы в него (использующий IME). Также, если я изменю слово в Вашем коде ("привет") к тому, который содержит японские символы, то это также не отобразит их.

Svisstack: Также спасибо за Вашу справку. Но когда я компилирую Ваш код, я получаю следующую ошибку:

warning: deprecated conversion from string constant to 'wchar_t*'
error: too few arguments to function 'int swprintf(wchar_t*, const wchar_t*, ...)'
error: at this point in file
warning: deprecated conversion from string constant to 'wchar_t*'
28
задан Josh Kelley 10 June 2010 в 01:05
поделиться

4 ответа

Попробуйте заменить cout на wcout, cin на wcin и строку на wstring. В зависимости от вашей платформы это может сработать:

#include <iostream>
#include <string>

int main() {
  std::wstring name;
  std::wcout << L"Enter your name: "; 
  std::wcin >> name;
  std::wcout << L"Hello, " << name << std::endl;
}

Есть и другие способы, но это своего рода ответ «минимальное изменение».

1
ответ дан 28 November 2019 в 03:30
поделиться

Вы можете делать простые вещи с помощью универсальной поддержки широких символов в выбранной вами ОС, но, как правило, в C ++ нет хорошей встроенной поддержки Unicode, поэтому в долгосрочной перспективе вам будет лучше, если вы изучите что-то вроде Отделение интенсивной терапии .

1
ответ дан 28 November 2019 в 03:30
поделиться

Вы получите много ответов о широких символах. Широкие символы, в частности wchar_t не равны Unicode. Их можно использовать (с некоторыми подводными камнями) для хранения Юникода, так же как и unsigned char. wchar_t чрезвычайно зависим от системы. Цитируем Стандарт Юникода, версия 5.2, глава 5:

С помощью wchar_t широкого символьного типа, ANSI/ISO C обеспечивает включение широких символов фиксированной ширины. ANSI/ISO C оставляет семантику широкого семантику широкого набора символов на усмотрение конкретной реализации, но требует, чтобы символы из переносимого набора исполнения C соответствовали своим эквивалентам широких символов по нулевому расширению.

и что

Ширина wchar_t зависит от компилятора и может составлять всего 8 бит. Следовательно, программы, которые должны быть переносимы через любой компилятор C или C++, не должны использовать wchar_t для хранения текста Юникода. Тип wchar_t предназначен для хранения определенных компилятором широких символов, которые могут быть символами Юникода в некоторых компиляторах.

Итак, он определяется реализацией. Вот две реализации: wchar_t в Linux имеет ширину 4 байта и представляет текст в кодировке UTF-32 (независимо от текущей локали). (Либо BE, либо LE, в зависимости от вашей системы, в зависимости от того, какая из них является родной.) В Windows, однако, есть wchar_t шириной 2 байта, и они представляют единицы кода UTF-16. Совсем другое дело.

Лучший путь: Изучите локали, так как вам понадобится это знание. Например, поскольку у меня среда настроена на использование UTF-8 (Unicode), следующая программа будет использовать Unicode:

#include <iostream>

int main()
{
    setlocale(LC_ALL, "");
    std::cout << "What's your name? ";
    std::string name;
    std::getline(std::cin, name);
    std::cout << "Hello there, " << name << "." << std::endl;
    return 0;
}

...

$ ./uni_test
What's your name? 佐藤 幹夫
Hello there, 佐藤 幹夫.
$ echo $LANG
en_US.UTF-8

Но в ней нет ничего юникодного. Она просто считывает символы, которые приходят как UTF-8 потому что у меня среда настроена именно так. Я мог бы так же легко сказать: "Черт, я частично чех, давайте использовать ISO-8859-2": Внезапно, программа получает ввод в ISO-8859-2, но поскольку она просто переводит его, это не имеет значения, программа все равно будет работать правильно.

Теперь, если бы этот пример считывал мое имя, а затем попытался записать его в XML-файл и тупо написал вверху, он был бы правильным, когда мой терминал был в UTF-8, но неправильным, когда мой терминал был в ISO-8859-2. В последнем случае, потребуется преобразовать его перед сериализацией в XML-файл. (Или просто напишите ISO-8859-2 в качестве кодировки для XML-файла.)

На многих POSIX-системах текущей локалью обычно является UTF-8, поскольку она дает несколько преимуществ пользователю, но это не гарантировано. Просто вывод UTF-8 на stdout обычно будет правильным, но не всегда. Скажем, я использую ISO-8859-2: если вы бездумно выведете на мой терминал "è" (0xE8) из ISO-8859-1, я увижу "č" (0xE8). Аналогично, если вы выведете UTF-8 "è" (0xC3 0xA8), я увижу (ISO-8859-2) "è" (0xC3 0xA8). Эта блевотина из неправильных символов была названа Mojibake.

Часто вы просто перетасовываете данные, и это не имеет большого значения. Обычно это происходит, когда вам нужно сериализовать данные. (Многие интернет-протоколы используют UTF-8 или UTF-16, например: если вы получили данные из терминала ISO-8859-2 или текстового файла, закодированного в Windows-1252, то вам придется их преобразовать, иначе вы будете посылать Mojibake.)

К сожалению, это касается состояния поддержки Unicode как в C, так и в C++. Вы должны помнить: эти языки действительно являются системно-агностическими, и не привязываются к какому-либо определенному способу работы. Это касается и наборов символов. Однако существует масса библиотек для работы с Unicode и другими наборами символов.

В конечном счете, все это не так уж сложно: Знайте, в какой кодировке находятся ваши данные, и знайте, в какой кодировке должен быть ваш вывод. Если они не совпадают, необходимо выполнить преобразование. Это относится к тому, используете ли вы std::cout или std::wcout. В моих примерах stdin или std::cin и stdout/std::cout иногда были в UTF-8, иногда в ISO-8859-2.

38
ответ дан 28 November 2019 в 03:30
поделиться
#include <stdio.h>
#include <wchar.h>

int main()
{
    wchar_t name[256];

    wprintf(L"Type a name: ");
    wscanf(L"%s", name);

    wprintf(L"Typed name is: %s\n", name);

    return 0;
}
1
ответ дан 28 November 2019 в 03:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: