我在uint8_t数组中有一个USB字符串描述符。例如:
0000:12 03 34 00 45 00 36 00 31 00 42 00 43 00 30 00 ..4.E.6.1.B.C.0.
0010:30 00 0.
(前两个字节是长度和描述符类型;剩下的字节是uint16_t类型的字符。)
我想在终端上打印这个,尽可能少的麻烦,最好不用和所有其他打印(发生像cout << "Hello, world" << endl;
)乱搞。
我特别想做的是:
cout << "Serial number is: " << some_cast_or_constructor( buf + 2, len - 2 ) << endl;
对于上面的字符串描述符,在终端上获得以下内容:
Serial number is: 4E61BC00
这是可能的吗,还是我必须钻研Unicode的奥秘?
[edit to add:]
Per @PaulMcKenzie,我尝试了这个程序:
#include <iostream>
#include <fstream>
#include <exception>
#include <string>
#include <locale>
int
main( int argc, char **argv )
{
char buf[] = { 34, 00, 45, 00, 36, 00, 31, 00, 42, 00, 43, 00, 30, 00, 30, 00 };
std::wcout << "Hello" << std::wstring( (const wchar_t *)buf, sizeof(buf) ) << std::endl;
return 0;
}
输出:user:/tmp$ g++ foo.cc
user:/tmp$ ./a.out
Hello??????????
user:/tmp$
在你的源代码中,我检测到两个错误:1-在你的USB原始数据(在顶部),值是十六进制,在你的buf[]值是十进制。应该这样写:
char buf[] = { 0x34, 0x00, 0x45, 0x00, 0x36, 0x00, 0x31, 0x00, 0x42,
0x00, 0x43, 0x00, 0x30, 0x00, 0x30, 0x00 };
2-在打印消息中,长度等于sizeof(但是),但它是'char'(1字节)而不是'wchar_t'(2字节)。应该这样写:
std::wcout << "Hello" << std::wstring( (const wchar_t *)buf, (sizeof(buf) >> 1) ) << std::endl;
并且,这段代码给出了Windows PC上的预期结果…在您的计算机上管理'wchar_t'之前,请确保没有大/小端序转换。
你能检查一下Linux下的size (wchar_t)吗?这篇文章Linux和for的wchar_t的区别和转换Windows假定wchar_t是一个32位的值。
如果您遇到这个问题是因为您在Linux上遇到Unicode,宽字符和类似的问题,那么我发现前进的最快方法是使用libiconv。您将在c++文档中读到的<codecvt>
头文件尚未在GNU libstdc++中实现(截至2016年10月)。
下面是演示libiconv
的快速示例程序:
#include <iostream>
#include <locale>
#include <cstdint>
#include <iconv.h>
#include <string.h>
int
main( int, char ** )
{
const char a[] = "ABC";
const wchar_t b[] = L"ABC";
const char c[] = u8"ABC";
const char16_t d[] = u"ABCDEF";
const char32_t e[] = U"ABC";
iconv_t utf16_to_utf32 = iconv_open( "UTF-32", "UTF-16" );
wchar_t wcbuf[32];
char *inp = (char *)d;
size_t inl = sizeof(d);
char *outp = (char *)wcbuf;
size_t outl = sizeof(wcbuf);
iconv( utf16_to_utf32, &inp, &inl, &outp, &outl );
std::wcout << "sizeof(a) = " << sizeof(a) << ' ' << a << std::endl
<< "sizeof(b) = " << sizeof(b) << ' ' << b << std::endl
<< "sizeof(c) = " << sizeof(c) << ' ' << c << std::endl
<< "sizeof(d) = " << sizeof(d) << ' ' << d << std::endl
<< "sizeof(e) = " << sizeof(e) << ' ' << e << std::endl
<< "Converted char16_t to UTF-32: " << std::wstring( wcbuf, (wchar_t *)outp - wcbuf ) << std::endl;
iconv_close( utf16_to_utf32 );
return 0;
}
输出结果:
user@debian:~/code/unicode$ ./wchar
sizeof(a) = 4 ABC
sizeof(b) = 16 ABC
sizeof(c) = 4 ABC
sizeof(d) = 14 0x7ffefdae5a40
sizeof(e) = 16 0x7ffefdae5a30
Converted char16_t to UTF-32: ABCDEF
user@debian:~/code/unicode$
注意std::wcout不能正确打印char16_t或char32_t。但是,您可以使用iconv
将UTF-16(这显然是您从u"STRING"
获得的)转换为UTF-32(这显然与最新型号的Linux系统上的wchar_t
兼容)。