std::wcout printing unicode characters but they are hidden - c++

So, the following code:
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>
#include <codecvt>
int main()
{
setlocale(LC_ALL, "");
std::wstring a;
std::wcout << L"Type a string: " << std::endl;
std::getline(std::wcin, a);
std::wcout << a << std::endl;
getchar();
}
When I type "åäö" I get some weird output. The terminal's cursor is indented, but there is no text behind it. If I use my right arrow key to move the cursor forward the "åäö" reveal themselves as I click the right arrow key.
If I include English letters so that the input is "helloåäö" the output is "hello" but as I click my right arrow key "helloåäö" appears letter by letter.
Why does this happen and more importantly how can I fix it?
Edit: I compile with Visual Studio's compiler on Windows. When I tried this exact code in repl.it (they use clang) it works like a charm. Is the problem caused by my code, Windows or Visual Studio?

Windows requires some OS-specific calls to set up the console for Unicode:
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>
// From fctrl.h:
// #define _O_U16TEXT 0x20000 // file mode is UTF16 no BOM (translated)
// #define _O_WTEXT 0x10000 // file mode is UTF16 (translated)
int main()
{
_setmode(_fileno(stdout), _O_WTEXT); // or _O_U16TEXT, either work
_setmode(_fileno(stdin), _O_WTEXT);
std::wstring a;
std::wcout << L"Type a string: ";
std::getline(std::wcin, a);
std::wcout << a << std::endl;
getwchar();
}
Output:
Type a string: helloåäö马克
helloåäö马克

Related

C++ Read UTF-8 (Lithuanian letters) symbols from txt file and show them in console application [duplicate]

This question already has answers here:
Read Unicode UTF-8 file into wstring
(7 answers)
Closed 1 year ago.
I need you help.
I'm using Windows 10 and Visual Studio Community compiler.
I managed to get Lithuanian letter to show on C++ console application using wstring and wcout.
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wstring a = L"ąėėąčėį";
wcout << a;
return 0;
}
Result is exactly what I wanted it to be
Now I want my program to read Lithuanian letters from Info.txt file.
This is how far I managed to get.
#include <iostream>
#include <fstream>
#include <io.h>
#include <fcntl.h>
#include <string>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wstring text;
wifstream fin("Info.txt");
getline(fin, text);
wcout << text;
return 0;
}
Returned string in console application shows different simbols.
But the returned string in console application shows different simbols.
In my belief a possible solution
I need to add L before the text like in previous example with wcout.
wstring a = L"ąėėąčėį";
But I'm still just learning C++ and I don't know how to do so in example with Info.txt
I need your help!
UTF8 needs std::ifstream, not wifstream. The latter is used in Windows as UTF16 file storage (not recommended in any system)
You can use SetConsoleOutputCP(CP_UTF8) to enable UTF8 printing, but that can run in to problems, specially in C++ 20
Instead, call _setmode and convert UTF8 to UTF16.
Make sure notepad saves the file in UTF8 (encoding option is available in Save window)
#include <iostream>
#include <fstream>
#include <string>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
std::wstring u16(const std::string u8)
{
if (u8.empty()) return std::wstring();
int size = MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, 0, 0);
std::wstring u16(size, 0);
MultiByteToWideChar(CP_UTF8, 0, u8.c_str(), -1, u16.data(), size);
return u16;
}
int main()
{
(void)_setmode(_fileno(stdout), _O_U16TEXT);
std::string text;
std::ifstream fin("Info.txt");
if (fin)
while (getline(fin, text))
std::wcout << u16(text) << "\n";
return 0;
}

Incorrect output of wchar_t characters in console c++

I try to print wchar_t characters by their integer index to console, but some of them displays like empty rectangles, while with some of them (Chinese characters for example) it works fine.
I have folowing code:
#include <iostream>
#include <iomanip>
#include <fcntl.h>
#include <io.h>
#include <conio.h>
#include <codecvt>
#include <cmath>
using namespace std;
int main() {
_setmode(_fileno(stdout), _O_U16TEXT);
wcout << L"Example 1: " << wchar_t(25500) << "\n";
wcout << L"Example 2: " << wchar_t(831) << "\n";
return 0;
};
And this is how it looks in console
I think it's something to do with console font (I'm using MS Gothic), but I don't know what

How to output unicode box drawing in C++?

Sorry for what may sound simple, but I am trying to draw just a simple box in Visual Studio 2017 using the unicode characters from https://en.wikipedia.org/wiki/Box-drawing_character using the code below
#include <iostream>
using namespace std;
int main()
{
cout << "┏━━━━━━━━━━━━━━━━━┓" << endl;
cout << "┃" << endl;
and so on...
However, whenever I run it all of the above code simply outputs as a ? wherever there should be a line.
So is it possible to output code like this directly to the console or for each character do I have to write the numeric values for each character?
Windows console supports UTF-16LE UNICODE.
You can use some box-driving library like PDCurses for example.
Otherwise you can use the following approach
#include <windows.h>
#include <cwchar>
class output_swap {
output_swap(const output_swap&) = delete;
output_swap operator=(output_swap&) = delete;
public:
output_swap( ) noexcept:
prevCP_( ::GetConsoleCP() )
{
::SetConsoleCP( CP_WINUNICODE );
::SetConsoleOutputCP( CP_WINUNICODE );
}
~output_swap() noexcept {
::SetConsoleCP( prevCP_ );
::SetConsoleOutputCP( prevCP_ );
}
private:
::DWORD prevCP_;
};
void draw_text(const wchar_t* text)
{
static ::HANDLE _out = ::GetStdHandle(STD_OUTPUT_HANDLE);
::DWORD written;
::WriteConsoleW( _out, text, std::wcslen(text), &written, nullptr );
}
int main(int argc, const char** argv) {
output_swap swap;
draw_text(L"┏━━━━━━━━━━━━━━━━━┓\n");
draw_text(L"┃ OK ┃\n");
draw_text(L"┗━━━━━━━━━━━━━━━━━┛\n");
return 0;
}
Also check you console font, in the console settings. You are probably need a raster font, but this is also working for Consolas for example.
If you need console io streams, which can work with unicode as well as box driwing you can use my library
Windows console apps can output wide strings (L"...") directly to the terminal if the mode is set correctly. Note the use of wcout as well. Save the following source in UTF-8 encoding:
#include <iostream>
#include <io.h>
#include <fcntl.h>
using namespace std;
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
wcout << L"┏━━━━━━━━━━━━━━━━━┓" << endl;
wcout << L"┃" << endl;
}
Compile with "cl /EHsc /utf-8 test.cpp". Output is:
┏━━━━━━━━━━━━━━━━━┓
┃

Why does the use of getline lead to "Debug assertion failed" message when setmodes are set as well?

So when debugging the code below I get a "Debug assertion failed" error window with the message:
Expression: ( (_Stream->_flag & _IOSTRG) || (fn = _fileno(_Stream),
(_textmode_safe(fn) == __IOINFO_TM_ANSI) && !_tm_unicode_safe(fn))))
However, if I comment out setmode lines, there is no problem at all.
Debugging always breaks at the line consisting getline. How should I modify the code to be able to scan data with getline?
#include "stdafx.h"
#include <iostream>
#include <string>
#include <io.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{
_setmode(_fileno(stdin), _O_U16TEXT);
_setmode(_fileno(stderr), _O_U16TEXT);
_setmode(_fileno(stderr), _O_U16TEXT);
std::string myString;
getline(std::cin, myString);
std::cout << "You typed in " << myString << std::endl;
std::cin.get();
return 0;
}
Since you appear to be setting some kind of UTC-16 mode on STDIN, wouldn't it make more sense to read from std::wcin (the wide-character version of std::cin) into a std::wstring? It's conceivable that this implementation-specific, non-standard feature has a requirement in that regard.
All the evidence I can find online (which isn't much) shows that this is the recommended approach for this mode.

Print content of a web page issue

I've no idea what's wrong with my code, but it does print nothing to stdout, although there is some content as shown in a debugger.
#include "stdafx.h"
#include <afx.h>
#include <afxinet.h>
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include "wininet.h"
using namespace std;
void DisplayPage(LPCTSTR pszURL)
{
CInternetSession session(_T("Mozilla/5.0"));
CStdioFile* pFile = NULL;
pFile = session.OpenURL(pszURL);
CString str = _T("");
while ( pFile->ReadString(str) )
{
wcout << str.GetString() << endl; // <-- here I expect some output, get nothing
// not even newline !
}
delete pFile;
session.Close();
}
// --- MAIN ---
int _tmain(int argc, _TCHAR* argv[])
{
DisplayPage( _T("http://www.google.com") );
cout << "done !" << endl;
cin.get();
return 0;
}
It is a console project. Console window pops up with message "done !" displayed only.
If anybody interested the issue was caused by non-OEM characters recieved from a web page trying to write to the default console (expecting OEM chars, translating mode). At the first non-OEM character std::wcout stops processing.
Either set the console to binary mode or convert recieved string to the appropriate encoding before sending to standard output.
#include <fcntl.h>
#include <io.h>
...
int old_transmode = _setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << str.GetString() << std::endl; // print wide string characters
...
_set_mode(_fileno(stdout), old_transmode); // restore original console output mode