I am having some trouble with unicode characters, and I was wondering if my code below is done in a proficient way. In short, I want to enter 2 words, the first one is blue
and the second one is blå
. They will be saved in two different text files and then the program will read from the files and print them correctly in the terminal. I am mainly interested in improvements of lines regarding unicode, _setmode
, wide characters etc. Here is the code:
#include <stdio.h>
#include <locale.h>
#include <wchar.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#define _O_U16TEXT 0x20000
#define _O_DEFAULT 0x4000
#define SIZE 1000
typedef struct {
wchar_t sweWord[SIZE]; //sweWord=Swedish Word
char engWord[SIZE]; //engWord=English Word
} Word;
void set_mode_to_UTF16() {
fflush(stdin);
fflush(stdout);
_setmode(_fileno(stdin), _O_U16TEXT);
_setmode(_fileno(stdout), _O_U16TEXT);
}
void set_mode_to_default() {
_setmode(_fileno(stdin), _O_DEFAULT);
_setmode(_fileno(stdout), _O_DEFAULT);
}
Word enterWord() {
Word aWord;
printf("Enter english word \"blue\": ");
scanf("%s", aWord.engWord);
printf("You entered: %s\n", aWord.engWord);
set_mode_to_UTF16();
wprintf(L"Enter swedish word \"blå\": ");
wscanf(L"%ls", aWord.sweWord);
wprintf(L"You entered: %ls\n", aWord.sweWord);
set_mode_to_default();
return aWord;
}
void saveWord(Word aWord) {
FILE *pFile1;
FILE *pFile2;
if(pFile1=fopen("ENGWORD.txt", "w")) {
fprintf(pFile1, "%s\n", aWord.engWord);
} else {
printf("Failed to save ENGWORD!\n");
}
fclose(pFile1);
set_mode_to_UTF16();
if(pFile2=fopen("SWEWORD.txt", "w")) {
_setmode(_fileno(pFile2), _O_U16TEXT);
fwprintf(pFile2, L"%ls\n", aWord.sweWord);
} else {
wprintf(L"Failed to save SWEWORD!\n");
}
fclose(pFile2);
set_mode_to_default();
}
Word loadWord() {
Word aWord;
FILE *pFile1;
FILE *pFile2;
if(pFile1=fopen("ENGWORD.txt", "r")) {
fscanf(pFile1, "%s", aWord.engWord);
} else {
printf("Failed to load ENGWORD!\n");
}
fclose(pFile1);
set_mode_to_UTF16();
if(pFile2=fopen("SWEWORD.txt", "r")) {
_setmode(_fileno(pFile2), _O_U16TEXT);
fwscanf(pFile2, L"%ls\n", aWord.sweWord);
} else {
wprintf(L"Failed to save SWEWORD!\n");
}
fclose(pFile2);
set_mode_to_default();
return aWord;
}
int main(void) {
int defaultMode;
defaultMode=_setmode(_fileno(stdin), _O_BINARY);
printf("Default mode is %d\n", defaultMode);
_setmode(_fileno(stdin), defaultMode); //mode is now in default.
Word wordToSave;
Word wordToLoad;
wordToSave=enterWord();
saveWord(wordToSave);
wordToLoad=loadWord();
printf("Loaded english word is %s\n", wordToLoad.engWord);
set_mode_to_UTF16();
wprintf(L"Loaded swedish word is %ls\n", wordToLoad.sweWord);
set_mode_to_default();
printf("Done! Signing off...\n");
return 0;
}
My output is:
Default mode is 16384
Enter english word "blue": blue
You entered: blue
Enter swedish word "blå": blå
You entered: blå
Loaded english word is blue
Loaded swedish word is blå
Done! Signing off...
There are 2 parts I am unsure of. Firstly, a quote from this website:
https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode?view=msvc-170
If you write data to a file stream, explicitly flush the code by using fflush before you use _setmode to change the mode.
I did this in the set_mode_to_UTF16
function, but not in the set_mode_to_default
function. Why should there be a difference between them?
Secondly, I have seen a lot of posts where setlocale
is used in order to change the locale to UTF-16. However, in my code I don't use it, which makes me wonder if I have done something wrong.
I wonder if I could get some input and feedback on my code as mentioned earlier and, if possible, help me get a better understanding of the 2 problems I was wondering about. Thanks in advance!
I use Windows 11, VSCode and MINGW-32.