У меня проблемы с записью французских символов в консоль в C ++. Строка загружается из файла с помощью std::ifstream
а также std::getline
а затем распечатывается на консоль с помощью std::cout
, Вот какая строка в файле:
La chaîne qui соответствует коду «TEST_CODE», а не по месту его проживания «fr».
И вот как строка печатается:
La chañne qui соответствует коду «TEST_CODE», а не к языку «fr».
Как я могу исправить эту проблему?
Проблема в том, что консоль использует другие кодовые страницы, чем остальная часть системы. Например, обычно системы Windows, настроенные для Северной и Южной Америки и Западной Европы, используют CP1252, но консоль в этих регионах использует CP437 или CP850.
Вы можете настроить кодовую страницу вывода консоли в соответствии с используемой кодировкой или преобразовать строки в соответствие с кодовой страницей вывода консоли.
Установите выходную кодовую страницу консоли:
SetConsoleOutputCP(GetACP()); // GetACP() returns the system codepage.
std::cout << "La chaîne qui correspond au code \"TEST_CODE\" n'a pas été trouvée à l'aide locale \"fr\".";
Или один из многих способов преобразования между кодировками (для этого требуется VS2010 или выше):
#include <codecvt> // for wstring_convert
#include <locale> // for codecvt_byname
#include <iostream>
int main() {
typedef std::codecvt_byname<wchar_t,char,std::mbstate_t> codecvt;
// the following relies on non-standard behavior, codecvt destructors are supposed to be protected and unusable here, but VC++ doesn't complain.
std::wstring_convert<codecvt> cp1252(new codecvt(".1252"));
std::wstring_convert<codecvt> cp850(new codecvt(".850"));
std::cout << cp850.to_bytes(cp1252.from_bytes("...été trouvée à...\n")).c_str();
}
В последнем примере предполагается, что вам действительно нужно конвертировать между 1252 и 850. Вам, вероятно, следует использовать функцию GetOEMCP (), чтобы выяснить фактическую целевую кодовую страницу, и исходная кодовая страница фактически зависит от того, что вы используете для исходного кода, а не по результату GetACP () на машине с запущенной программой.
Также обратите внимание, что эта программа опирается на что-то, что не гарантируется стандартом: кодировка wchar_t будет разделена между локалями. Это верно для большинства платформ — обычно некоторая кодировка Unicode используется для wchar_t во всех локалях — но не во всех.
В идеале вы могли бы просто использовать UTF-8 везде, и следующее будет работать нормально, как это происходит на других платформах в наши дни:
#include <iostream>
int main() {
std::cout << "La chaîne qui correspond au code \"TEST_CODE\" n'a pas été trouvée à l'aide locale \"fr\".\n";
}
К сожалению, Windows не может поддерживать UTF-8 таким образом, не отказавшись ни от UTF-16 в качестве кодировки wchar_t, ни от 4-байтного wchar_t, ни от нарушения требований стандарта и нарушения стандартных программ соответствия.
Если вы хотите писать символы Unicode в консоли, вы должны сделать некоторые инициализация:
_setmode(_fileno(stdout), _O_U16TEXT);
Тогда ваши французские символы отображаются правильно (я проверил это с помощью Consolas
как мой консольный шрифт):
#include <fcntl.h>
#include <io.h>
#include <iostream>
#include <ostream>
#include <string>
using namespace std;
int main()
{
// Prepare console output in Unicode
_setmode(_fileno(stdout), _O_U16TEXT);//
// Build Unicode UTF-16 string with French characters
//
// 0x00EE - LATIN SMALL LETTER I WITH CIRCUMFLEX
// 0x00E9 - LATIN SMALL LETTER E WITH ACUTE
// 0x00E0 - LATIN SMALL LETTER A WITH GRAVE
wstring str(L"La cha");
str += L'\x00EE';
str += L"ne qui correspond au code \"TEST_CODE\" ";
str += L"n'a pas ";
str += L'\x00E9';
str += L't';
str += L'\x00E9';
str += L" trouv";
str += L'\x00E9';
str += L"e ";
str += L'\x00E0';
str += L" l'aide locale \"fr\".";// Print the string to the console
wcout << str << endl;
}
Вы можете прочитать следующие сообщения в блоге Майкла Каплана:
Более того, если вы читаете какой-то текст из файла, вы должны знать, какие кодирование используется: UTF-8? UTF-16LE? UTF-16BE? Какая-то конкретная кодовая страница? Затем вы можете конвертировать из определенной кодировки в Unicode UTF-16 и использовать UTF-16 внутри приложения Windows. Для преобразования из некоторой кодовой страницы (или из UTF-8) в UTF-16 вы можете использовать MultiByteToWideChar()
API, или же Класс помощника преобразования ATL CA2W
.