Исходя из опытов выше, возникает вопрос: а чем различаются эти два варианта подключения кириллицы к проекту?
Практически всем. На самом деле, у вас есть две сущности - ваша программа и терминал. Ваша программа читает данные из stdin и пишет в stdout/stderr. Терминал же занимается тем, что отображает данные на экран. Для вас критически важно, чтобы программа передавала данные в той кодировке, в которой их ожидает увидеть терминал.
Соотвественно, когда вы вызываете
SetConsoleOutputCP(1251)
, вы говорите терминалу "ожидай данные в кодировке СР1251". Это плохо по нескольким причинам:
- Это чисто виндова функция. Она не переносима на другие платформы
- СР1251 - однобайтовая кодировка и ее лучше не использовать в 21 веке. Нужен юникод.
- Другие программы, работающие в этом же терминале (например echo) не знают что вы поменяли кодировку терминала. Потому вы и видите мусор.
Когда вы вызываете
setlocale
- вы говорите своей программе "возьми настройки кодировки из окружения и выдавай текст в ней". В результате вы подстраиваетесь под терминал и используете ту кодировку, в которой он работает. Скорее всего это будет юникод. В этом варианте все минусы превращаются в плюсы - это переносимо, это юникод, остальные программы будут работать нормально.
Кстати, вызывать setlocale с параметром Russian не совсем верно. Нужно использовать пустую строку -"". Интересно, что я уже второй раз вижу на тостере именно "Russian". Кажется, где-то по рунету гуляет неправильный пример.