Принятие очень простой программы, что:
Это настолько просто, который первая вещь, которую каждый изучает.
Но моя проблема состоит в том, что я не знаю, как сделать то же самое, если я ввожу имя с помощью японских символов.
Так, если Вы знаете, как сделать это в 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*'
Попробуйте заменить 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;
}
Есть и другие способы, но это своего рода ответ «минимальное изменение».
Вы можете делать простые вещи с помощью универсальной поддержки широких символов в выбранной вами ОС, но, как правило, в C ++ нет хорошей встроенной поддержки Unicode, поэтому в долгосрочной перспективе вам будет лучше, если вы изучите что-то вроде Отделение интенсивной терапии .
Вы получите много ответов о широких символах. Широкие символы, в частности 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.
#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;
}