How to insert NULL character in std::wstringstream?
Asked Answered
B

2

6

I need to construct a multi-string (REG_MULTI_SZ) in C++ from a list of values represented in a std::vector<std::wstring>.

This is what first came to mind but was of course incorrect:

std::wstring GetMultiString(std::vector<std::wstring> Values)
{
    std::wstringstream ss;

    for (const std::wstring& Value : Values) {
        ss << Value;
        ss << L"\0";
    }

    ss << L"\0";

    return ss.str();
}

Upon inspection, the returned string didn't have any embedded NULL characters.

Boyhood answered 24/1 at 15:41 Comment(4)
ss << L"\0"; is same as ss << L""; and does nothing. The both point to null-terminated char literals, how much nulls are there after the first one, doesn't matterPeer
@273K Yeah, I am aware of that, but it is very easy to make a mistake hence the Q&A. I wonder if using C++ string literals (L"\0"s) would behave differently?Boyhood
"As expected"? You wouldn't be asking the question if that was the expected result.Weeks
Yes, L"\0"s is a string containing the zero char.Peer
B
6

The solution is actually quite simple:

std::wstring GetMultiString(std::vector<std::wstring> Values)
{
    std::wstringstream ss;

    for (const std::wstring& Value : Values) {
        ss << Value;
        ss.put(L'\0');
    }

    ss.put(L'\0');

    return ss.str();
}

The reason why the original code failed to accomplish anything is that ss << L"\0"; is the same as ss << L""; and therefore does nothing.

You can also pass 0 instead of L'\0':

        ss.put(0);

Or use << and std::ends:

        ss << std::ends;

Or use << and C++ string literal operator""s:

        using namespace std::string_literals;
        // ...
        ss << L"\0"s;

Or even basic_ostream::write:

        const wchar_t Null = 0;
        // ...
        ss.write(&Null, 1); // sizeof(Null) / sizeof(wchar_t)
Boyhood answered 24/1 at 15:41 Comment(9)
To make this answer better you should explain why the original code failed and how this approach fixes it.Ladawnladd
The fix here is in single-quotes. You could use put or continue using operator<<; doesn't matter.Outcross
alternatively, ss.write which is an unformatted writeCreole
@Ladawnladd I updated the question as per your suggestion.Boyhood
Add that to the answer, not the question. The question states the problem and the answer explains it and how to fix it.Ladawnladd
@Ladawnladd Reading comprehension faiil on my end, hopefully this fixes it.Boyhood
@Outcross I prefer put() since it is more clear that you are putting a single character in the stream and you can't use wrong quotes.Boyhood
Note that you don't have to use a character constant L'\0', you could just use 0.Weeks
@MarkRansom Good point, but I don't think being more explicit hurts.Boyhood
P
4

There's an obscure manipulator in the standard library for this too:

ss << std::ends;
Peristalsis answered 25/1 at 5:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.