Проблемы кодировки символов Visual Studio C++

Оптимизация последнего вызова может саботироваться не вызов хвоста. В языке Common LISP:

(defun f () (1+ (f)))
15
задан MPelletier 15 May 2014 в 19:03
поделиться

2 ответа

Прежде чем идти дальше, я должен упомянуть, что то, что вы делаете, не совместимо с c / c ++. В спецификации указано в 2.2, какие наборы символов допустимы в исходном коде. Там немного, и все используемые символы находятся в ascii. Итак ... Все, что ниже, касается конкретной реализации (как оказалось, VC2008 на машине с локалью США).

Для начала у вас есть 4 символа в строке cout и 4 символа на выход. Таким образом, проблема заключается не в кодировке UTF8, поскольку она объединяет несколько исходных символов с меньшим количеством глифов.

От исходной строки до отображения на консоли все эти вещи играют свою роль:

  1. Какая кодировка исходного файла находится в (т.е. как ваш файл C ++ будет виден компилятором)
  2. Что ваш компилятор делает со строковым литералом, и какую исходную кодировку он понимает
  3. , как ваш << интерпретирует закодированную строку, которую вы передаете
  4. , какая кодировка ожидает консоль
  5. , как консоль переводит этот вывод в глиф шрифта.

Теперь ...

1 и 2 довольно простые. Похоже, что компилятор угадывает, в каком формате находится исходный файл, и декодирует его во внутреннее представление. Он генерирует соответствующий блок данных строкового литерала в текущей кодовой странице независимо от исходной кодировки. Я не смог найти явных подробностей / контроля по этому поводу.

3 еще проще. За исключением управляющих кодов, << просто передает данные для char *.

4 управляется SetConsoleOutputCP . Он должен по умолчанию использовать вашу системную кодовую страницу по умолчанию. Вы также можете определить, какой у вас есть, с помощью GetConsoleOutputCP (вводом управляют по-другому, через SetConsoleCP )

5 - забавный вариант. Я ударил головой, пытаясь понять, почему я не могу заставить é правильно отображаться, используя CP1252 (западноевропейский, windows). Оказывается, мой системный шрифт не имеет глифа для этого символа и услужливо использует глиф моей стандартной кодовой страницы (заглавная Theta, то же самое, что я получил бы, если бы не вызвал SetConsoleOutputCP). Чтобы исправить это, мне пришлось изменить шрифт, который я использую на консолях, на Lucida Console (настоящий шрифт).

Некоторые интересные вещи, которые я узнал, глядя на это:

  • кодировка исходного кода не имеет значения, если поскольку компилятор может это понять (в частности, изменение его на UTF8 не изменило сгенерированный код. Моя "é" строка все еще была закодирована с помощью CP1252 как 233 0 )
  • VC выбирает кодовую страницу для строковых литералов, которые я не контролирую.
  • контролировать то, что показывает консоль, более болезненно, чем то, что я ожидал

Итак ... что это для вас значит? Вот несколько советов:

  • не используйте не-ascii в строковых литералах. Используйте ресурсы, где вы управляете кодировкой.
  • убедитесь, что вы знаете, какую кодировку ожидает ваша консоль, и что ваш шрифт имеет глифы для представления отправляемых вами символов.
  • если вы хотите чтобы выяснить, какая кодировка используется в вашем случае, я бы посоветовал вывести фактическое значение символа как целое число. char * a = "é"; std :: cout << (unsigned int) (unsigned char) a [0] действительно показывает 233 для меня, что является кодировкой в ​​CP1252.
15
ответ дан 1 December 2019 в 01:45
поделиться

Я пробовал этот код:

#include <iostream>
#include <fstream>
#include <sstream>

int main()
{
    std::wstringstream wss;
    wss << L"àéêù";
    std::wstring s = wss.str();
    const wchar_t* p = s.c_str();
    std::wcout << ws.str() << std::endl;

    std::wofstream file("C:\\a.txt");
    file << p << endl;

    return 0;
}

Отладчик показал, что все wss, s и p имеют ожидаемые значения (т.е. «àéêù»), как и выходной файл. Однако то, что появилось в консоли, было óúÛ¨.

Таким образом, проблема заключается в консоли Visual Studio, а не в C ++. Воспользовавшись отличным ответом Бахбара, я добавил:

    SetConsoleOutputCP(1252);

в качестве первой строки, после чего вывод консоли появился так, как должен.

3
ответ дан 1 December 2019 в 01:45
поделиться
Другие вопросы по тегам:

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