С++ Печать специальных символов ascii в консоль Windows

После 2 часов поиска и проб различных методов, я рву на себе волосы, пытаясь вывести на консоль специальные символы ascii! (С++)

typedef unsigned char UCHAR;

int main()
{
  UCHAR c = '¥';
  cout << c;

  return 0;
}

Почему этот код печатает Ñ (209) вместо ¥ (165)???

Я пытался:

SetConsoleCP(CP_UTF8);
SetConsoleOutputCP(CP_UTF8);

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

Кто-то еще подсказал, что шрифт консоли нужно менять через реестр. Но это смешно. Я не хочу, чтобы моим конечным пользователям приходилось менять значения реестра просто для того, чтобы запустить мою программу...

действительно странно то, что если я печатаю все символы ascii в файл (используя ofstream), они правильно отображаются как в блокноте, так и в редакторе визуальной студии (профессионал 2012 года).

ofstream file("ASCII.txt");;
if (file.is_open())
{
    UCHAR c = 0;
    for (int i = 0; i < 256; i++)
    {
        c++;
        file << c << "\t|\t" << (int)c << endl;
    }
}
file.close();

Буду признателен за любую оказанную помощь. Спасибо!


person Garrett Fleischer    schedule 26.06.2015    source источник
comment
Бьюсь об заклад, команда type делает то же самое, что и ваша программа. Откройте окно командной строки и введите type ASCII.txt и посмотрите, что будет выведено на консоль.   -  person PaulMcKenzie    schedule 27.06.2015
comment
Поищите в Интернете кодовые страницы Microsoft.   -  person Thomas Matthews    schedule 27.06.2015
comment
Символ 165 недопустим в UTF-8. Установлен самый старший бит, что означает, что это символ продолжения, состоящий из 2+ байтов.   -  person kfsone    schedule 27.06.2015
comment
@PaulMcKenzie Я не знаком с командой type, и беглый поиск в Google дал результаты только для ожидаемых функций typeof и typedef. Я чувствую, что вы, возможно, неправильно прочитали мой вопрос. Этот раздел кода внизу был предназначен только для проверки реальных значений ascii. Я не собираюсь использовать его в моей финальной программе.   -  person Garrett Fleischer    schedule 27.06.2015
comment
@BenSeawalker Он имеет в виду команду DOS type.   -  person kfsone    schedule 27.06.2015
comment
Что у вас есть для вашего набора символов в «Свойства» -> «Общие» -> «Настройки проекта по умолчанию» -> «Набор символов»?   -  person kfsone    schedule 27.06.2015
comment
@BenSeawalker Мои указания указаны Open a command-line window Вы знакомы с командным окном? Это окно с подсказкой C:\> (или похожей)   -  person PaulMcKenzie    schedule 27.06.2015
comment
@PaulMcKenzie Прошу прощения, я пропустил часть «Открыть окно командной строки». ›_‹   -  person Garrett Fleischer    schedule 27.06.2015
comment
@kfsone Он был настроен на юникод. Я изменил его на многобайтный, но в консоли все равно нет разницы.   -  person Garrett Fleischer    schedule 27.06.2015
comment
@BenSeawalker хорошо. нет проблем. Если type дает тот же результат, что и ваша программа, проблема заключается в настройке кодовой страницы консоли, о которой упоминали другие.   -  person PaulMcKenzie    schedule 27.06.2015
comment
@ThomasMatthews Я также пробовал SetConsoleOutputCP (1250) безрезультатно.   -  person Garrett Fleischer    schedule 27.06.2015
comment
Какая кодировка исходного файла?   -  person kfsone    schedule 27.06.2015
comment
@BenSeawalker Забудьте на мгновение о программе и попробуйте заставить type работать (при условии, что она ведет себя так же, как ваша программа). Существует команда chcp — попробуйте использовать ее, чтобы заставить type работать правильно. Как только вы найдете нужную кодовую страницу, вернитесь к своей программе и попытайтесь сделать то же самое с SetConsoleOutputCP.   -  person PaulMcKenzie    schedule 27.06.2015
comment
@kfsone Н/Д Я просто пытаюсь напрямую напечатать '¥'   -  person Garrett Fleischer    schedule 27.06.2015
comment
@BenSeawalker Похоже, chcp 65001 меняет консоль на UTF-8, как показано здесь: stackoverflow.com/questions/15470271/ Так что, возможно, вам следует указать 65001 как кодовая страница?   -  person PaulMcKenzie    schedule 27.06.2015
comment
@PaulMcKenzie спасибо за помощь. Моя текущая кодовая страница консоли — 437 (OEM United States). Тип печатает только первые 25 строк данного текстового файла. Тип справки говорит, что в качестве параметра принимает только имя файла, поэтому нет -all, /full и т. д. для отображения всего файла.   -  person Garrett Fleischer    schedule 27.06.2015
comment
¥ не 165 в cp (437). Следовательно, почему так важно, в какой кодировке находится ваш исходный файл. DUH.   -  person kfsone    schedule 27.06.2015
comment
@kfsone в этом нет необходимости. В любом случае я пробовал SetConsoleCP() и SetConsoleOutputCP() с каждым кодом, найденным здесь: msdn.microsoft.com/en-us/library/windows/desktop/ ни один из которых никак не повлиял на вывод. Я также открыл cmd, использовал dhcp 1252 и запустил свою программу из этого окна, а не из отладчика VS, и до сих пор никаких изменений.   -  person Garrett Fleischer    schedule 27.06.2015
comment
Намерен 'DUH' на себя за то, что не поймал это раньше, извините :)   -  person kfsone    schedule 27.06.2015


Ответы (1)


Добро пожаловать в боль кодирования :(

#include <iostream>
#include <windows>

int main() {
    SetConsoleCP(437);
    SetConsoleOutputCP(437);
    std::cout << (char)157 << "\n";
}

Генерирует:

Результат компиляции и выполнения

Проблема в том, что ваш исходный файл не находится в CP437, и поэтому символ имеет значение, отличное от того, которое вы пытаетесь напечатать (как вы заметили, в исходном файле значение равно 165, что отличается от персонаж в CP437).

https://en.wikipedia.org/wiki/Code_page_437

person kfsone    schedule 27.06.2015
comment
SetConsoleCP(437); SetConsoleOutputCP(437); cout << '¥'; все еще печатает 'С' :( - person Garrett Fleischer; 27.06.2015
comment
о хорошо, спасибо за помощь. Не могли бы вы опубликовать ссылку на сайт, с которого вы получили свои коды ascii? Все, что я видел, утверждают, что char равен 190, а не 157. - person Garrett Fleischer; 27.06.2015
comment
Это в конце ответа. cout << '¥'; у меня работает, если я сохраняю файл с кодировкой CP 437. - person kfsone; 27.06.2015
comment
Я сохранил все свои файлы .cpp и .h с кодировкой 437 и очистил/пересобрал проект. еще никакого эффекта. :( - person Garrett Fleischer; 27.06.2015
comment
Не берите в голову. Я перезапустил VS и теперь все работает без нареканий! Спасибо @kfsone, я бы никогда не подумал изменить кодировку моих исходных файлов. ха-ха - person Garrett Fleischer; 27.06.2015