@MavShieldt

В чём разница способов подключения кириллицы?

Здравствуйте! Учу С++, программирование и в целом развиваюсь в сфере IT.

Сегодня обнаружил в консольке винды команду echo, позволяющую выводить на экран некую надпись.
99lWUFp5in8.jpg
Решил попробовать вызвать эту команду через C++ и функцию system. Хочу заметить, что всегда использую вариант подключения кириллицы через SetConsoleCP(1251); из windows.h, как и в коде ниже.
#include "stdafx.h"
#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
	SetConsoleCP(1251);
	SetConsoleOutputCP(1251);
	system("echo ДАННЫЕ УДАЛЕНЫ");
	system("pause");
    return 0;
}

Результатом выполнения программы оказались кракозябры, вылезающие при неподключённой кириллице.
mjQwKFifRvI.jpg
Однако, когда я решил использовать в коде функцию setlocale, вывод на экран стал соответствовать моей цели.
#include "stdafx.h"
#include <iostream>
using namespace std;

int main()
{
	setlocale(LC_ALL, "Russian");
	system("echo ДАННЫЕ УДАЛЕНЫ");
	system("pause");
    return 0;
}

8XblUj_u3tc.jpg
Исходя из опытов выше, возникает вопрос: а чем различаются эти два варианта подключения кириллицы к проекту? Если что, я спрашиваю не только про результат работы, но и про сами процессы, происходящие в системе при использовании этих функций.
Заранее спасибо за ответ.
  • Вопрос задан
  • 5846 просмотров
Решения вопроса 1
@lorc
Исходя из опытов выше, возникает вопрос: а чем различаются эти два варианта подключения кириллицы к проекту?


Практически всем. На самом деле, у вас есть две сущности - ваша программа и терминал. Ваша программа читает данные из stdin и пишет в stdout/stderr. Терминал же занимается тем, что отображает данные на экран. Для вас критически важно, чтобы программа передавала данные в той кодировке, в которой их ожидает увидеть терминал.

Соотвественно, когда вы вызываете SetConsoleOutputCP(1251), вы говорите терминалу "ожидай данные в кодировке СР1251". Это плохо по нескольким причинам:

  • Это чисто виндова функция. Она не переносима на другие платформы
  • СР1251 - однобайтовая кодировка и ее лучше не использовать в 21 веке. Нужен юникод.
  • Другие программы, работающие в этом же терминале (например echo) не знают что вы поменяли кодировку терминала. Потому вы и видите мусор.


Когда вы вызываете setlocale - вы говорите своей программе "возьми настройки кодировки из окружения и выдавай текст в ней". В результате вы подстраиваетесь под терминал и используете ту кодировку, в которой он работает. Скорее всего это будет юникод. В этом варианте все минусы превращаются в плюсы - это переносимо, это юникод, остальные программы будут работать нормально.

Кстати, вызывать setlocale с параметром Russian не совсем верно. Нужно использовать пустую строку -"". Интересно, что я уже второй раз вижу на тостере именно "Russian". Кажется, где-то по рунету гуляет неправильный пример.
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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