Problems printing Unicode characters in Windows

Feb 16, 2021 at 7:28pm
How do I properly format the wcout statement with the L switch in my example code? As it is, it just prints out garbage to the console window.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <io.h>
#include <fcntl.h>
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);

    std::string t_prefix = "\u2554";
    std::string t_middle = "";
    std::string t_suffix = "\u2557\n\u2551";
    int max_message_length = 33;

	for (int i = t_middle.length(); i < max_message_length; i++) {

		t_middle = "\u2550" + t_middle;

	}
    std::string complete_message = t_prefix + t_middle + t_suffix;


    std::wcout << complete_message.c_str();

}
Last edited on Feb 17, 2021 at 3:18pm
Feb 16, 2021 at 7:59pm
- What operating system?
- What compiler? (be specific as possible)
- What font is the console window?

Edit:
How does this render for you:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);

    std::wstring t_prefix = L"\u2554";
    std::wstring t_middle;
    std::wstring t_suffix = L"\u2557\n\u2551";
    int max_message_length = 33;

	for (int i = t_middle.length(); i < max_message_length; i++) {

		t_middle = L"\u2550" + t_middle;

	}
    std::wstring complete_message = t_prefix + t_middle + t_suffix;


    std::wcout << complete_message.c_str();
}
Last edited on Feb 16, 2021 at 8:02pm
Feb 16, 2021 at 8:02pm
What does this have to do with recursion?
Anyway, try using wstring instead of string and put L in front of the string literals: L"\u2554".

You might want to use UTF-8 instead. For example, this works for me on linux. You seem to be on Windows, but it might also work for you:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

int main()
{
    std::string t_prefix = "╔";
    std::string t_middle;
    std::string t_suffix = "╗\n║";
    int max_message_length = 33;

	for (int i = t_middle.size(); i < max_message_length; ++i)
		t_middle = "═" + t_middle;

    std::string complete_message = t_prefix + t_middle + t_suffix;
    std::cout << complete_message << '\n';
}


╔═════════════════════════════════╗
║

Last edited on Feb 16, 2021 at 8:08pm
Feb 16, 2021 at 8:14pm
That appears to not work for me, at least with the combination of:
- Windows 10, cmd or powershell, Consolas and Lucida Console font
- gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)

Produces:
ΓòöΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓòÉΓ ...

The string --> wstring replacements works, though.

[Yeah I know my compiler is pretty out of date at this point, I should update it]
Last edited on Feb 16, 2021 at 8:20pm
Feb 16, 2021 at 9:02pm
Windows seems to require that kick in the butt with _setmode to properly display the desired characters, the compiler doesn't appear to matter. I tried both Visual Studio and Code::Blocks.

It doesn't seem to matter if you are encoding for UTF-8 or UTF-16.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <io.h>
#include <fcntl.h>
#include <iostream>
#include <string>

int main()
{
   _setmode(_fileno(stdout), _O_U8TEXT);

   std::wstring t_prefix { L'\u2554' };
   std::wstring t_suffix { L"\u2557\n\u2551" };

   std::wstring t_middle;

   const size_t max_message_length { 33 };

   for (size_t i { t_middle.size() }; i < max_message_length; ++i)
   {
      t_middle += L'\u2550';
   }

   std::wstring complete_message { t_prefix + t_middle + t_suffix };

   std::wcout << complete_message << '\n';
}

Windows does weird things at times.
Last edited on Feb 17, 2021 at 3:34pm
Feb 16, 2021 at 9:55pm
Thanks. I am relearning C++.
I forgot a lot of it from after I had a stroke.

May I ask why you have this way std::wstring t_prefix { L'\u2554' }; instead of std::wstring t_prefix = L"\u2554";

I have not seen them declared that way :P off to google the way you done it.
also i was using eclipse but eclipse for some reason wont show up right in its console window. so I went to VS 2019 and codeBlocks.
Last edited on Feb 16, 2021 at 9:58pm
Feb 17, 2021 at 1:02am
Why L'\u2554' instead of L"\u2554"?

L'\u2554' represents a single character, not a literal string of two or more characters. L"\u2557\n\u2551" is a literal string of 3 characters.

Personal preference, mostly, but it also gives the compiler a chance to catch possible typing errors. If I had typed L'\2554' (no Unicode designator) the compiler would have warned about it.

A similar reason why I use "uniform initialization" as much as possible. int x { 15 }; instead of int x = 15;.
https://www.geeksforgeeks.org/uniform-initialization-in-c/

Initializing the for loop iterator variable on line 17 with the type of size_t (or std::size_t) instead of int. Since the comparison condition uses the size member function of a string, what is the return type of that function? Type size_type, an unsigned integral type. With a C++ container (std::string is a container) the container's size_type is usually defined as synonym of std::size_t.
https://en.cppreference.com/w/cpp/types/size_t

I personally use size_t almost exclusively when doing an old school for loop that iterates over a container. When doing a for loop using iterators or a range-based for loop I use auto for the type. That let's the compiler select the type so I don't have to remember.
https://www.geeksforgeeks.org/introduction-iterators-c/
https://en.cppreference.com/w/cpp/language/range-for

Using iterators instead of array indices has distinct advantages.
https://stackoverflow.com/questions/131241/why-use-iterators-instead-of-array-indices

With iterators accessing elements in a C++ containers uses much the same interface. Some containers have an operator[] to access individual elements, some don't. All C++ standard library containers have iterators defined to access elements.

Justcus wrote:
I am relearning C++.

Take a peek at Learn C++, then. Decently comprehensive from-the-ground-up tutorials.
https://www.learncpp.com/

It doesn't cover some of the more "esoteric" aspects of C++, that is where cppreference comes in handy. A C & C++ reference:
https://en.cppreference.com/w/

NOT a tutorial, though there is a lot of example code. NOT for a beginner or someone relearning C++ basics again.
Last edited on Feb 17, 2021 at 1:48am
Feb 17, 2021 at 1:06am
Justcus wrote:
I went to VS 2019 and codeBlocks.

Maybe I'm biased but those two IDEs are what I routinely use. Having both is a good idea because there are times one compiler barfs up on code and the other doesn't. And vice versa.

Using two different compilers makes it easier to write generic code as well. Visual Studio has some quirks because it is by Microsoft.

IDEs are great, but also knowing how to do command-line compiling can be beneficial.
Last edited on Feb 17, 2021 at 1:07am
Feb 17, 2021 at 3:39am
@ Furry Guy, @dutch, @Ganado First I would like to say "Thanks You" to everyone here that responded. The reason I was using Eclipse is because I was also using it for Java and mindcraft modding, and never really had a problem with it before this issue. (sort of use what you know) I know somewhere in the setting is a place to change the encoding for the console window (but then again it can be a Windows Issue). When eclipse was giving me garbage characters I used the same file but in a CMD window and it printed out perfectly with the extended/Unicode character codes. I am using MinGW64 version from about 2 weeks ago.

@dutch I had 2 people in 2 different forums
What this has to do with recursion?
. Isn't recursion what the for loop does for me?

@Furry Guy yeah I agree command-line compiling is beneficial! I grew up in the days of DOS and have used Linux boxes before. I thought this was gonna be easy since I use to do batch file programming and made console menus just echoing the ALT codes to the console window.

My next step is to take the single.cpp file and move to multiple.cpp files with each it own class. I am making a hangman game BTW if I never said so before.

Once I get it finished I will be posting the completed source code for people to looks at and use if there is a place on this forum to do so.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <iostream>
#include <io.h>
#include <fcntl.h>

void PrintMessage(std::string message, bool print_top = true, bool print_bottom = true){

    const size_t max_message_length { 33 };

    if(print_top){

        std::wstring top_prefix { L'\u2554' };
        std::wstring top_suffix { L"\u2557\n\u2551" };
        std::wstring top_middle;

        for (size_t i { top_middle.size() }; i < max_message_length; ++i){

            top_middle += L'\u2550';
        }

    std::wstring complete_message { top_prefix + top_middle + top_suffix };
    std::wcout << complete_message;

    }
    else{

        std::wcout << L"\u2551";

    }

    bool front = true;
    for (int i = message.length(); i < max_message_length; i++){

        if (front){
            message = " " + message;
        }else{
            message = message + " ";
        }

        front = !front;

    }

    std::wcout << message.c_str();

    if(print_bottom){

        std::wstring bottom_prefix { L"\u2551\n\u2560" };
        std::wstring bottom_suffix { L'\u2563' };
        std::wstring bottom_middle;

        for (size_t i { bottom_middle.size() }; i < max_message_length; ++i){

            bottom_middle += L'\u2550';
        }
    std::wstring complete_message { bottom_prefix + bottom_middle + bottom_suffix };
    std::wcout << complete_message;
    }

    else{

        std::wcout << L"\u2551";

    }

}
int main(){

    _setmode(_fileno(stdout), _O_U8TEXT);
    PrintMessage("HANGMAN");

}


The middle part which you help me with was my road block. TYVM AGAIN :P
Feb 17, 2021 at 4:40am
Justcus wrote:
Isn't recursion what the for loop does for me?

Not really, though it is similar to looping.
https://www.cprogramming.com/tutorial/lesson16.html
Feb 17, 2021 at 5:10am
Ganado wrote:
I know my compiler is pretty out of date at this point, I should update it

You could be using Bloodshed's Dev C++, Mingw/GCC 3.4.2.
Feb 17, 2021 at 2:15pm
lol :)
Feb 17, 2021 at 3:11pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include <iostream>
#include <io.h>
#include <fcntl.h>

void PrintMessage(std::string message, bool print_top = true, bool print_bottom = true) {

    const size_t max_message_length{ 33 };

    if (print_top) {

        std::wstring top_prefix{ L'\u2554' };
        std::wstring top_suffix{ L"\u2557\n\u2551" };
        std::wstring top_middle;

        for (size_t i{ top_middle.size() }; i < max_message_length; ++i) {

            top_middle += L'\u2550';
        }

        std::wstring complete_message{ top_prefix + top_middle + top_suffix };
        std::wcout << complete_message;

    }
    else {

        std::wcout << L"\u2551";

    }

    bool front = true;
    for (size_t i{ message.size() }; i < max_message_length; ++i) {

        if (front) {
            message = " " + message;
        }
        else {
            message = message + " ";
        }

        front = !front;

    }

    std::wcout << message.c_str();

    if (print_bottom) {

        std::wstring bottom_prefix{ L"\u2551\n\u2560" };
        std::wstring bottom_suffix{ L"\u2563\n" };
        std::wstring bottom_middle;

        for (size_t i{ bottom_middle.size() }; i < max_message_length; ++i) {

            bottom_middle += L'\u2550';
        }
        std::wstring complete_message{ bottom_prefix + bottom_middle + bottom_suffix };
        std::wcout << complete_message;
    }

    else {

        std::wcout << L"\u2551\n";

    }

}

void DrawHangman(int guess_count = 0)
{
    if (guess_count >= 1)
        PrintMessage("|", false, false);                       // I want to use the single line box code for the rope │
    else                                                       // instead of the pipe char |
        PrintMessage("", false, false);

    if (guess_count >= 2)
        PrintMessage("|", false, false);
    else
        PrintMessage("", false, false);

    if (guess_count >= 3)
        PrintMessage("-_-", false, false);                     // I want to use ☺ instead of -_-
    else
        PrintMessage("", false, false);

    if (guess_count == 4)
        PrintMessage("/  ", false, false);

    if (guess_count == 5)
        PrintMessage("/| ", false, false);

    if (guess_count >= 6)
        PrintMessage("/|\\", false, false);

    else
        PrintMessage("", false, false);

    if (guess_count >= 7)
        PrintMessage("|", false, false);
    else
        PrintMessage("", false, false);

    if (guess_count == 8)
        PrintMessage("/  ", false, false);

    if (guess_count >= 9)
        PrintMessage("/ \\", false, false);
    else
        PrintMessage("", false, false);
}

int main() {

    _setmode(_fileno(stdout), _O_U8TEXT);
    PrintMessage("HANGMAN");
    DrawHangman(9);
	PrintMessage("+-------------+", false, false);
	PrintMessage("|             |", false);
	PrintMessage("Available letters", false, true);

    return 0;

}


I have a problem I been trying to figure out also. trying to get this part of the above code to accept Unicode characters too. If you guys think this should be a new posting let me know and I will make one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    bool front = true;
    for (size_t i{ message.size() }; i < max_message_length; ++i) {

        if (front) {
            message = " " + message;
        }
        else {
            message = message + " ";
        }

        front = !front;

    }

    std::wcout << message.c_str();

when I try to change void PrintMessage(std::string message, to void PrintMessage(std::wstring message, it wont compile.
above code displays the following:

╔═════════════════════════════════╗
║             HANGMAN             ║
╠═════════════════════════════════╣
║                |                ║
║                |                ║
║               -_-               ║
║               /|\               ║
║                |                ║
║               / \               ║
║         +-------------+         ║
║         |             |         ║
╠═════════════════════════════════╣
║        Available letters        ║
╠═════════════════════════════════╣

I would like to use the single line box Unicode for the rope and the smiley face unicode for the head. It would be used like PrintMessage(L"\u263a"); Hopefully to get the white head. The floor of gallows I wanted to do them in single box characters.

Last edited on Feb 17, 2021 at 3:25pm
Feb 17, 2021 at 3:31pm
You are having problems when you try to change the first parameter of PrintMessage because there are several lines of code you are still using non-Unicode strings.

Line 5: void PrintMessage(std::wstring message, bool print_top = true, bool print_bottom = true)

Line 34: message = L' ' + message; or if you prefer message = L" " + message;

Line 37: message = message + L' '; or if you prefer message = message + L" ";

Line 114: PrintMessage(L"HANGMAN");

And so on. You forgot to add the L to the string literals in your Hangman and Printmessage functions and in main. If you are going to use std::wstring, you need to use L"some string" consistently.

You should also include the <string> header. Don't rely on a compiler automatically including other needed headers.
Last edited on Feb 17, 2021 at 3:43pm
Feb 17, 2021 at 3:37pm
LOL I was working my way to that solution. I also had to add L in every PrintMessage() in DrawHangman(); also. Should I mark this topic answered/closed?
Feb 17, 2021 at 4:19pm
Got'cher smiley face:
80
81
   if (guess_count >= 3)
      PrintMessage(L"☺", false, false);

and

solid planking:
116
117
   PrintMessage(L"┌─────────────┐", false, false);
   PrintMessage(L"│             │", false);

Sometimes copying'n'pasting the actual character(s) from Windows' character map makes drawing basic graphics easier than using the Unicode numbers.
Feb 17, 2021 at 9:15pm
Yeah when i use the actual characters I get garbage. the only thing that seems to work for me is the L\u#### codes. I tried the code above that dutch showed using the actual characters. and it printed the 3 garbage characters and I tried it with the wstring as suggested and it still printed out the same I even cleaned the project just in case the exe was stale. I may make a DrawGallows(); function to use a for loop to create the solid planking so it would stay in center just in case I change the width. But anyways You have been a big help. I never expected you to explain and give me tutorial links and such as you did. Most of the time I get short condescending reply. I had one java help forum person tell me not to use the help forum as my personal teacher. go figure :) I always try to research and figure out stuff myself before I post anything for me it like a last resort to post on a forum because I know what type of responses I usually get. or they down mark my question so far that it get auto closed.

But as of right now my program outputs:

╔═════════════════════════════════╗
║             HANGMAN             ║
╠═════════════════════════════════╣
║                ┋                ║
║                ┋                ║
║                ☺                ║
║               /┃\               ║
║                ┃                ║
║               / \               ║
║         ┏━━━━━━━━━━━━━┓         ║
║         ┃             ┃         ║
╠═════════════════════════════════╣
║        Available letters        ║
╠═════════════════════════════════╣

Last edited on Feb 17, 2021 at 9:16pm
Topic archived. No new replies allowed.