wcout can't print wstring from wcin in Windows. But in Linux(WSL2 Ubuntu 20.04), it works fine.
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
using namespace std;
int main(int argv, char** argc)
{
locale mylocale("");
locale::global(mylocale);
wcout.imbue(mylocale);
wcin.imbue(mylocale);
wstring name;
wcout << L"너의 이름은?";
getline(wcin, name);
wcout << name << endl;
return 0;
}
Following is my expected output.
너의 이름은?김철수
김철수
But, 000 is printed.
너의 이름은?김철수
000
OR just blank
너의 이름은?김철수
sometimes 'P', '#'...
Console Active code page: 65001 checked.
wcin puts wstring in name properly.
name.size() shows the number of literal that i typed.
It's okay with get input from a file.
I use D2coding font.
Related
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;
}
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åäö马克
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.
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
I try to run the code blow in Xcode 4.2:
int main(int argc, const char * argv[])
{
locale loc("chs");
locale::global(loc);
wstring text(L"你好");
wcout << text << endl;
return 0;
}
I got a error "Thread 1:signal SIGABRT".
Can you Tell me why the error happen or how to use wstring and wcout to output the Chinese words?
You don't. Mac, like other Unix systems, uses UTF8 while Windows uses "Unicode" (UTF-16).
You can print that perfectly well on Mac by using string and cout instead of wstring and wcout.
ADDENDUM
This sample works great. Compile with g++ and run as-is.
#include <string>
#include <iostream>
using namespace std;
int main(int arg, char **argv)
{
string text("汉语");
cout << text << endl;
return 0;
}
The crash is coming from the call to locale(). This SO answer seems related.
As mentioned by Mahmoud Al-Qudsi, you don't need it as you can use UTF-8 in a normal string object:
#include <string>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
string text("你好");
cout<<text<<endl;
return 0;
}
Produces:
$ ./test
你好
EDIT: Oops, too late :)