简体   繁体   English

C ++问题,将wchar_t *转换为字符串

[英]C++ Issue, Converting wchar_t* to string

I am having a problem here. 我在这里有问题。 This is in Unicode. 这是Unicode。 I have a stringtable that has values in it, separated by ; 我有一个字符串表,其中包含值,以;分隔; . I've been at this all day and I always end up with immediate runtime errors. 我整天都在忙碌,而我总是总是会立即遇到运行时错误。

Stringtable looks like: Stringtable看起来像:

`blah;blah;foo;bar;car;star`

Then the code: 然后是代码:

// More than enough size for this
const int bufferSize = 2048;

// Resource ID to a StringTable
int resid = IDS_MAP;
wchar_t readMap[bufferSize];            
resid = LoadString(NULL, resid, readMap, bufferSize);  

wchar_t* line;
line = wcstok(readMap,L";");

while (line != NULL) {

    line = wcstok(NULL,L";");
    wstring wstr(line); // Problem
    string str(wstr.begin(), wstr.end()); // Problem

    MessageBox(0,line,0,0) // No problem
}

The trouble is when I try to convert wchar_t* line to a wstring , to string . 问题是当我尝试将wchar_t* line转换为wstring ,转换为string If I uncomment those two lines, it runs fine and message box shows properly. 如果我取消注释这两行,则可以正常运行,并且消息框显示正确。

Any ideas? 有任何想法吗? Asking this question here was my last resort. 在这里问这个问题是我的最后选择。 Thanks. 谢谢。

This statement: 这个说法:

line = wcstok(readMap,L";");

Reads the first delimited line in the buffer. 读取缓冲区中的第一line OK. 好。

However, in your loop, this statement: 但是,在您的循环中,此语句:

line = wcstok(NULL,L";");

Is at the top of the loop and is thus throwing away that first line on the 1st iteration and then reading the next delimited line . 在循环的顶部 ,因此在第一次迭代中丢弃了第一行,然后读取了下一个line Eventually, your loop will reach the end of the buffer and wcstok() will return NULL, but you are not checking for that condition before using line : 最终,您的循环将到达缓冲区的末尾,并且wcstok()将返回NULL,但是在使用line之前,您无需检查该条件:

line = wcstok(readMap,L";"); // <-- reads the first line

while (line != NULL) {

    line = wcstok(NULL,L";"); // <-- 1st iteration throws away the first line
    wstring wstr(line); // <-- line will be NULL on last iteration

    //...
}

The line = wcstok(NULL,L";"); line = wcstok(NULL,L";"); statement needs to be moved to the bottom of the loop instead: 语句需要移到循环的底部

wchar_t* line = wcstok(readMap, L";");

while (line != NULL)
{
    // use line as needed...

    line = wcstok(NULL, L";");
}

I would suggest changing the while loop into a for loop to enforce that: 我建议将while循环更改为for循环以强制执行以下操作:

for (wchar_t* line = wcstok(readMap, L";"); (line != NULL); line = wcstok(NULL, L";"))
{
    // use line as needed...
}

On the other hand, since you are using C++, you should consider using std:wistringstream and std:getline() instead of wcstok() : 另一方面,由于使用的是C ++,因此应考虑使用std:wistringstreamstd:getline()代替wcstok()

#include <string>
#include <sstream>

// after LoadString() exits, resid contains the
// number of character copied into readMap...
std::wistringstream iss(std::wstring(readMap, resid));

std::wstring line;
while (std::getline(iss, line, L';'))
{
    // use line as needed...
}

But either way, this statement is just plain wrong: 但是,无论哪种方式,此声明都是错误的:

string str(wstr.begin(), wstr.end()); // Problem

This statement will work correctly only if the std::wstring contains ASCII characters in the #0 - #127 range. 该声明将正常工作只有在std::wstring包含在#0 ASCII字符- #127范围内。 For non-ASCII characters, you have to perform a data conversion instead to avoid data loss for Unicode characters > U+00FF. 对于非ASCII字符, 必须执行数据转换,以避免Unicode字符> U + 00FF的数据丢失。

Since you are running on Windows, you can use the Win32 API WideCharToMultiByte() function: 由于您在Windows上运行,因此可以使用Win32 API WideCharToMultiByte()函数:

std::wstring line;
while (std::getline(iss, line, L';'))
{
    std::string str;

    // optionally substitute CP_UTF8 with any ANSI codepage you want...
    int len = WideCharToMultiByte(CP_UTF8, 0, line.c_str(), line.length(), NULL, 0, NULL, NULL);
    if (len > 0)
    {
        str.resize(len);
        WideCharToMultiByte(CP_UTF8, 0, line.c_str(), line.length(), &str[0], len, NULL, NULL);
    }

    // use str as needed...
    MessageBoxW(0, line.c_str(), L"line", 0);
    MessageBoxA(0, str.c_str(), "str", 0);
}

Or, if you are using C++11 or later, you can use the std::wstring_convert class (only for UTF-8/16/32 conversions, though): 或者,如果您使用的是C ++ 11或更高版本,则可以使用std::wstring_convert类(不过仅适用于UTF-8 / 16/32转换):

#include <locale> 

std::wstring line;
while (std::getline(iss, line, L';'))
{
    std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> conv;
    std::string str = conv.to_bytes(line);

    // use str as needed...
    MessageBoxW(0, line.c_str(), L"line", 0);
    MessageBoxA(0, str.c_str(), "str", 0);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM