I assume the set-up you're using is to have the source saved using cp1251 (Cyrillic Windows) and to have the console using cp866 (Cyrillic DOS). (This will be the default set up on Russian versions of Windows.) The problem you're running into seems to be that setting the locale as you do causes output to be converted from cp1251 to cp866, but does not cause the inverse conversion for input. So when you read a character in, the program gets the cp866 representation. This cp866 representation, when output, is incorrectly treated as a cp1251 representation and converted to cp866, resulting in the ф to д transformation.
I think the conversions is just done by the CRT based on the C locale, but I don't know how to enable a similar conversion for input. There are different options for getting your program to work.
- Manually convert input data from cp866 to cp1251 before echoing it.
- Replace
setlocale(LC_ALL,"rus")
which changes how the CRT deals with output with calls to SetConsoleCP(1251); SetConsoleOutputCP(1251);
which will instead changes the console's behavior (and the changes will persist for the lifetime of the console rather than the lifetime of your program).
- Replace uses of cin and cout with Windows APIs using UTF-16. Microsoft's implementation of the standard library forces the use of legacy encodings and causes all sorts of similar problems on Windows. So just avoid it altogether.
Here's an example of the second option:
#include <iostream>
#include <clocale>
#include <Windows.h>
void main(){
char c;
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
std::cout << "Я хочу видеть это по-русски!\n";
std::cin >> c;
std::cout << c;
}
Assuming the source is cp1251 encoded then the output will appear correctly and an input ф will not be transformed into a д.