2
std::regex regexpy("y:(.+?)\"");
std::smatch my;
regex_search(value.text, my, regexpy);
y = my[1];

std::wstring wide_string = std::wstring(y.begin(), y.end());
const wchar_t* p_my_string = wide_string.c_str();
wchar_t* my_string = const_cast<wchar_t*>(p_my_string);

URLDownloadToFile(my_string, aDest);

I'm using Unicode, the encoding of the source string is ASCII, UrlDownloadToFile expands to UrlDownloadToFileW (wchar_t*) the code above compiles in debug mode, but with a lot of warnings like:

warning C4244: 'argument': conversion from 'wchar_t' to 'const _Elem', possible loss of data

So do I ask, how I could convert a std::string to a wchar_t?

Cesar
  • 41
  • 2
  • 5
  • 16
  • 1
    Does this answer your question? [How to convert wstring into string?](https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string) – Ben Cottrell Nov 10 '20 at 18:06
  • How to convert wstring into string? – Cesar Nov 10 '20 at 18:07
  • 1
    Or even this one https://stackoverflow.com/questions/2573834/c-convert-string-or-char-to-wstring-or-wchar-t – Ben Cottrell Nov 10 '20 at 18:07
  • Is this in general, or is it on a specific platform? Can you use SDKs like ICU? Do you know the encoding of the source string (simple ASCII? UTF-8? 8895-1? 1252? 437?) – Eljay Nov 10 '20 at 18:17
  • @Eljay simple ASCII – Cesar Nov 10 '20 at 18:21
  • Please post a [mcve]. The `UrlDownloadToFileW` should have no issues with any conversion warnings if you are giving it the arguments of the correct type. Second thing is that [the documentation](https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms775123(v=vs.85)?redirectedfrom=MSDN) does not show a two argument function. – PaulMcKenzie Nov 10 '20 at 18:31
  • 1
    You don't need the `const_cast` anyway, because `UrlDownloadToFileW()` takes a `const wchar_t*` to begin with, so `c_str()` will work fine as-is: `URLDownloadToFile(wide_string.c_str(), ...);` – Remy Lebeau Nov 10 '20 at 18:52
  • What is `y`? From the statement `y = my[1];` it seems that `y` is a `std::sub_match`, but `sub_match` does not have `begin` or `end` methods. – Raymond Chen Nov 10 '20 at 18:56
  • @RaymondChen `std::sub_match` has a [conversion operator](https://en.cppreference.com/w/cpp/regex/sub_match/str) for `std::string` in this example – Remy Lebeau Nov 10 '20 at 19:00
  • @RemyLebeau Thanks. That was the missing bit. The declaration was `std::string y = my[1];` I was using `auto y = my[1];`. – Raymond Chen Nov 10 '20 at 20:54

2 Answers2

1

First off, you don't need the const_cast, as URLDownloadToFileW() takes a const wchar_t* as input, so passing it wide_string.c_str() will work as-is:

URLDownloadToFile(..., wide_string.c_str(), ...);

That being said, you are constructing a std::wstring with the individual char values of a std::string as-is. That will work without data loss only for ASCII characters <= 127, which have the same numeric values in both ASCII and Unicode. For non-ASCII characters, you need to actually convert the char data to Unicode, such as with MultiByteToWideChar() (or equivilent), eg:

std::wstring to_wstring(const std::string &s)
{
    std::wstring wide_string;

    // NOTE: be sure to specify the correct codepage that the
    // str::string data is actually encoded in...
    int len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), s.size(), NULL, 0);
    if (len > 0) {
        wide_string.resize(len);
        MultiByteToWideChar(CP_ACP, 0, s.c_str(), s.size(), &wide_string[0], len);
    }

    return wide_string;
}

URLDownloadToFileW(..., to_wstring(y).c_str(), ...);

That being said, there is a simpler solution. If the std::string is encoded in the user's default locale, you can simply call URLDownloadToFileA() instead, passing it the original std::string as-is, and let the OS handle the conversion for you, eg:

URLDownloadToFileA(..., y.c_str(), ...);
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

There is a cross-platform solution. You can use std::mbtowc.

std::wstring convert_mb_to_wc(std::string s) {
    std::wstring out;
    std::mbtowc(nullptr, 0, 0);
    int offset;
    size_t index = 0;
    for (wchar_t wc;
           (offset = std::mbtowc(&wc, &s[index], s.size() - index)) > 0;
           index += offset) {
        out.push_back(wc);
    }
    return out;
}

Adapted from an example on cppreference.com at https://en.cppreference.com/w/cpp/string/multibyte/mbtowc .

Anonymous1847
  • 2,568
  • 10
  • 16