I'm using Microsoft Windows 10 with mingw-w64 (gcc version 8.1.0, x86_64-posix-sjlj-rev0, Built by MinGW-W64 project) with cmd
. When I try to print or store and then print a Spanish character on the Windows console, it shows an error. For example I tried to execute this program:
#include <stdio.h>
int main(void) {
char c[20];
printf("pía\n");
scanf("%s", c);
printf("%s", c);
}
If I introduce some Spanish characters the returned sentence is OK but the printed one at the beginning shows an error:
pía
laíóñaú
laíóñaú
Some solutions suggest putting setlocale()
function but the results are the same. Other solution is put the UTF-8 unicode compatibility on region settings:
But now the error is the opposite, the printed one is OK but when I introduce a strange character the console doesn't show it:
pía
lía
l
It is a bit frustrating since all the solutions I have seen are solved with the above or by setting setlocale()
, but none of them work for me and I don't know why.
As Mofi say in comments I try to use SetConsoleCP()
and SetConsoleOutputCP()
to change the code page of the console. Without fully understanding how these functions work, with the same code as above, I ran several examples with wrong results:
pía | p├¡a | p├¡a | pía
lía | lía | lía | lía
l | l | lía | la
input: 65001 output 65001 | input: 65001 output 850 | input: 850 output 850 | input: 850 output 65001
How I don't fully understand this functions I don't know why in the last example, the console don't show the accented stored character but in the printed one it does and in the example above the opposite happens.
I played around with this for a while and the only thing that worked was using _setmode()
to set the stdin
and stdout
to take in wide characters, and then working with wchar_t
instead of char
to store the text. This code works as intended on my machine:
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
int main(void) {
_setmode(_fileno(stdin), _O_WTEXT);
_setmode(_fileno(stdout), _O_WTEXT);
wchar_t c[20];
wprintf(L"pía\n");
wscanf(L"%ls", c);
wprintf(L"%ls", c);
}
EDITED: I changed the parameter of _setmode
from _O_U16TEXT
to _O_WTEXT
to avoid implementation issues resulting from how the length of wchar_t
is either 2 or 4 bytes based on the compiler.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With