Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Print and store spanish characters (á, é, í, ñ...) in cmd

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:

enter image description here

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.

EDIT

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.

like image 413
Rafael Hernández Marrero Avatar asked Nov 07 '22 03:11

Rafael Hernández Marrero


1 Answers

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.

like image 167
directquest Avatar answered Nov 15 '22 04:11

directquest