The below code fails to print the wide character:
#include <ncurses.h>
using namespace std;
int main(void){
initscr();
printw("█");
getch();
endwin();
}
This code seems to work on some computers and not others, although all the libraries are installed correctly.
(The terminal is capable of displaying extended char!)
I compiled this using:
g++ -std=c++14 widechartest.cpp -o widechar -lncursesw
Could somebody let me know what the problem is?
Thanks 8)
You didn't initialize the locale. The manual page points this out:
The library uses the locale which the calling program has initialized.
That is normally done with setlocale:
setlocale(LC_ALL, "");
If the locale is not initialized, the library assumes that characters
are printable as in ISO-8859-1, to work with certain legacy programs.
You should initialize the locale and not rely on specific details of
the library when the locale has not been setup.
Related
First, briefly,
My computer with Window11OS showed this console window.
?? ? ?? C++????
C:\Users\MYNAME\source\repos\20220816ConsoleApplication1\x64\Debug\20220816ConsoleApplication1.exe (process 17604) exited with code 0.
and quetionmarks are NOT what I intended.
I think I need to use intentionally UNICODE here.
But I don't know how to do, I failed once; I'll explain later.
So, this is the code that I want to fix. And I'm using Visual Studio as Windows Console Application(C++/WInRT) for this solution-file.
#include <iostream>
int main()
{
using namespace std;
/*표준 출력 스트림으로 문장을 출력함
근데 왜 한글이 물음표로 나올까*/
cout << "나의 첫 번째 C++프로그램" << endl;
return 0;
}
But VS's error-list showed me the below.
Warning C4566 character represented by universal-character-name '\uB098' cannot be represented in the current code page (1252)
What property I've changed to build successfully was the below
VS's upper menu > Project > Properties(the lowest item) > Configuration Properties > C/C++ > Precompiled Headers > Precompiled Header : Use(/Yu) --I CHANGED IT TO-->> Not Using Precompiled Headers
I also had tried to change "Language" property just like the screenshot below, but I had failed to build at all, even question-marks hadn't shown.
What I had tried to show Hangeul-language instead of question-marks but failed.
On Windows, use the following to set the console stdout to Unicode mode. Save the file with UTF-8 w/ BOM encoding, or UTF-8 without BOM and compile with the /utf-8 switch. You Windows needs to support the Korean language or at least use a console font that supports Korean characters such as NSimSun.
test.cpp: compiled with "cl /W4 /EHsc /utf-8 test.cpp"
#include <iostream>
#include <io.h>
#include <fcntl.h>
int main()
{
using namespace std;
_setmode(_fileno(stdout), _O_U16TEXT);
wcout << L"나의 첫 번째 C++프로그램" << endl;
return 0;
}
Output (cut/paste from cmd window):
나의 첫 번째 C++프로그램
The following call to sprintf fails when compiled for i386 arch. using the Android NDK. I have tried compiling with both GCC and clang, and the result is the same. I'm using android-ndk-r10e (with APP_STL set to gnustl_shared with GCC, c++_shared with clang). It works as (I?) intended when compiling for ARM with the same configuration, and furthermore when I'm compiling for i386 Linux with GCC 5.2.
int n = sprintf(buf, "\xc0%s", "test"); // n == 0, strlen(buf) == 0
After the call, buf is empty rather than containing the expected char sequence "\xc0test". sprintf appears to ignore everything after the first non-ASCII character. The following code writes "test" to buf, leaving out the last byte:
sprintf(buf, "%s\xc0", "test"); // strlen(buf) == 4
On the other hand, this works fine:
sprintf(buf, "%s", "test\xc0"); // strlen(buf) == 5
I'm perplexed.
This is known Android problem. The problem resides in Android libc implementation (Bionic), which is fairly incomplete in terms of conforming to standards. In particular, Bionic stdio implementation doesn't support non-ASCII characters properly.
This simple test prints strlen(buf)=4 when being built by Android NDK r10e:
#include <stdio.h>
#include <string.h>
int main()
{
char buf[256];
sprintf(buf, "%s\xc0", "test");
printf("strlen(buf)=%d\n", strlen(buf));
return 0;
}
Solution: use CrystaX NDK - alternative fork of the Google's Android NDK, where that problems were fixed. The example above works properly if being built by the CrystaX NDK 10.3.1:
strlen(buf)=5
The article Unicode apps in the MinGW-w64 wiki explains the following example for an Unicode application, e.g. _main.c_:
#define UNICODE
#define _UNICODE
#include <tchar.h>
int _tmain(int argc, TCHAR * argv[])
{
_tprintf(argv[1]);
return 0;
}
The above code makes use of tchar.h mapping, which allows it to both compile in Unicode and non-Unicode mode. [...] The -municode option is still required when linking if Unicode mode is used.
So I used
C:\> i686-w64-mingw32-gcc main.c -municode -o hello
_tmain.c:1:0: warning: "UNICODE" redefined
#define UNICODE
^
<command-line>:0:0: note: this is the location of the previous definition
to compile a Unicode application. But, when I run it, it returns
C:\> hello Süßer
S³▀er
So the Unicode string is wrong. I used the latest version 4.9.2 of MinGW-w64, i686 architecture and tried the Win32 and POSIX theads variants, both result in the same error. My operating system is 32-bit German Windows 7. When I used the Unicode codepage (chcp 65001), I have to use the font "Lucida Console". With this setting I get a similar error:
C:\> hello Süßer
S��er
I want to use a parameter with "ü" or "ß" in a Windows C++ program.
Solution
nwellnhof is right: The problem is the output on the console. This problem is explained in Unicode part 1: Windows console i/o approaches und Unicode part 2: UTF-8 stream mode. The latter gives a solution for Visual C++ - it worked also with Intel C++ 15. This blog post does "not yet consider the g++ compiler. All this code is Visual C++ specific. However, [the blog author has] done generally the same with g++, and [he] will probably discuss that in a third installment."
I want to open a file, which name is given by a parameter. This works simple, e. g. main.c:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
if ( argc > 1 ) {
// The output will be wrong, ...
cout << argv[1] << endl;
// but the name of this file will be right:
fstream fl_rsl(argv[1], ios::out);
fl_rsl.close();
}
return 0;
}
and the compilation without unicode mode
C:\> g++ main.cpp -o hello && hello Süßer
It's console output is still wrong, but the created filename is right. This is okay for me.
Why
cout<< "привет";
works well while
wcout<< L"привет";
does not? (in Qt Creator for linux)
GCC and Clang defaults to treat the source file as UTF-8. Your Linux terminal is most probably configured to UTF-8 as well. So with cout<< "привет" there is a UTF-8 string which is printed in a UTF-8 terminal, all is well.
wcout<< L"привет" depends on a proper Locale configuration in order to convert the wide characters into the terminal's character encoding. The Locale needs to be initialized in order for the conversion to work (the default "classic" aka "C" locale doesn't know how to convert the wide characters). Use std::locale::global (std::locale ("")) for the Locale to match the environment configuration or std::locale::global (std::locale ("en_US.UTF-8")) to use a specific Locale (similar to this C example).
Here's the full source of the working program:
#include <iostream>
#include <locale>
using namespace std;
int main() {
std::locale::global (std::locale ("en_US.UTF-8"));
wcout << L"привет\n";
}
With g++ test.cc && ./a.out this prints "привет" (on Debian Jessie).
See also this answer about dangers of using wide characters with standard output.
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
int main(void) {
_setmode(_fileno(stdout), _O_U16TEXT);
wprintf(L"\x043a\x043e\x0448\x043a\x0430 \x65e5\x672c\x56fd\n");
return 0;
}
returns error at compilation: _O_U16TEXT was not declared in this scope
Is this a show-stopper with this compiler ?
Well, there's a simple workaround: just use values of these constants instead of their names. For example, _O_U16TEXT is 0x00020000 and _O_U8TEXT is 0x00040000.
I've just confirmed that it works with _setmode using g++ 4.8.1 on Windows 10:
#include <iostream>
#include <fcntl.h>
#include <io.h>
#include <stdio.h>
int main() {
_setmode(_fileno(stdout), 0x00020000); // _O_U16TEXT
std::wcout << L"Русский текст\n";
}
Don't even bother with it.
Your user needs to set the font of his console to a unicode one (Lucida Console for example), or else it won't display anything. If you're targeting East Asia, where the default font is unicode aware, it'll display fine, but in Europe, you have to change the font manually.
User's won't change their console font because you write it in the readme. They won't even read the readme, they'll just see that it displays garbage, and they will think the program doesn't work.
Also, it's a farly new function VS 2005, so you need to link the VS 2005 redistributeable, msvcr50.dll, or newer (mingw link to msvcrt.dll by default). If you don't do this, the text, won't be displayed at all.
And I think a simple pipe will kill your new and shiny unicode text. Let's say your exe named a.exe. I'm pretty sure, that a.exe | more will NOT display unicode text.