C++: socket encoding (working with TeamSpeak) -
as i'm working on program teamspeak server, need retrieve names of online users i'm doing sockets - that's working fine far.
in ui i'm displaying clients in listbox working. nevertheless i'm having problems wrong displayed characters , symbols in listbox. i'm using following code:
//... auto getclientlist() -> void{ = 0; querystring.str(""); querystring.clear(); querystring << clientlist << " \n"; send(sock, querystring.str().c_str(), strlen(querystring.str().c_str()), null); teamspeak::getanswer(1); while(p_1 != -1){ p_1 = lastlog.find(l"client_nickname=", spos + 1); if(p_1 != -1){ spos = p_1; p_2 = lastlog.find(l" ", p_1); temporary = lastlog.substr(p_1 + 16, p_2 - (p_1 + 16)); users[i].assign(temporary.begin(), temporary.end()); sendmessage(hwnd_2, lb_addstring, (wparam)null, (lparam)(lptstr)(users[i].c_str())); i++; } else{ spos = 0; p_1 = 0; break; } } teamspeak::getanswer(0); } //...
i've checked lastlog
, temporary
, users[i]
(by writing them file), of them have no encoding problem characters or symbols (for example andrè
). if add string directly:sendmessage(hwnd_2, lb_addstring, (wparam)null, (lparam)(lptstr)l"andrè"
, displayed correctly in listbox.
what might issue here, problem code or else?
update 1:
i continued working on problem , considered word olè!
receiving socket. result got, following:o (79) | l (108) | � (-61) | � (-88) | ! (33)
.
how can convert char array
wstring
containing correct characters?
solution:
@isanae mentioned in post, std::wstring_convert
-template did trick me, thank much!
many things can go wrong in code, , don't show of it. what's particularly lacking definition of variables.
assuming users[i]
contains meaningful data, don't how encoded. ascii? utf-8? utf-16? fact can output file , read editor doesn't mean anything, editors able guess @ encoding.
if utf-16 (the native encoding on windows), see no reason code not work. 1 way check break debugger , @ individual bytes in users[i]
. if see every character value less 128 followed 0, it's utf-16.
if not utf-16, you'll need convert it. there variety of ways this, multibytetowidechar may easiest. make sure set codepage
same encoding used sender. may cp_utf8
, or actual codepage.
note hardcoding string non-ascii characters doesn't either, you'd first have find out encoding of file itself. know versions of visual c++ convert source file utf-16 if encounters non-ascii characters, may happened you.
o (79) | l (108) | � (-61) | � (-88) | ! (33)
.how can convert char array wstring containing correct characters?
this utf-8 string. has converted utf-16 windows can use it.
this portable, c++11 solution on implementations sizeof(wchar_t) == 2
. if not case, char16_t
, std::u16string
may used, recent version of visual c++ of writing (2015 rc) doesn't implement std::codecvt
char16_t
, char32_t
.
#include <string> #include <codecvt> std::wstring utf8_to_utf16(const std::string& s) { static_assert(sizeof(wchar_t)==2, "wchar_t needs 2 bytes"); std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv; return conv.from_bytes(s); } std::string utf16_to_utf8(const std::wstring& s) { static_assert(sizeof(wchar_t)==2, "wchar_t needs 2 bytes"); std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> conv; return conv.to_bytes(s); }
windows-only:
#include <string> #include <cassert> #include <memory> #include <codecvt> #include <windows.h> std::wstring utf8_to_utf16(const std::string& s) { // getting required size in characters (not bytes) of // output buffer const int size = ::multibytetowidechar( cp_utf8, 0, s.c_str(), static_cast<int>(s.size()), nullptr, 0); // error handling assert(size != 0); // creating buffer enough characters in std::unique_ptr<wchar_t[]> buffer(new wchar_t[size]); // converting utf8 utf16 const int written = ::multibytetowidechar( cp_utf8, 0, s.c_str(), static_cast<int>(s.size()), buffer.get(), size); // error handling assert(written != 0); return std::wstring(buffer.get(), buffer.get() + written); } std::string utf16_to_utf8(const std::wstring& ws) { // getting required size in bytes of output buffer const int size = ::widechartomultibyte( cp_utf8, 0, ws.c_str(), static_cast<int>(ws.size()), nullptr, 0, nullptr, nullptr); // error handling assert(size != 0); // creating buffer enough characters in std::unique_ptr<char[]> buffer(new char[size]); // converting utf16 utf8 const int written = ::widechartomultibyte( cp_utf8, 0, ws.c_str(), static_cast<int>(ws.size()), buffer.get(), size, nullptr, nullptr); // error handling assert(written != 0); return std::string(buffer.get(), buffer.get() + written); }
test:
// utf-8 string const std::string s = {79, 108, -61, -88, 33}; ::messageboxw(0, utf8_to_utf16(s).c_str(), l"", mb_ok);
Comments
Post a Comment