CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 11 of 11
  1. #1
    Join Date
    Mar 2009
    Posts
    166

    string/wstring question

    Hello,

    I am having problems with string/wstring code. In the code below Buffer returns a string.

    This first code works, but I noticed that if the returned string from Buffer contained embedded null characters, it would terminate the string when passed to wstring.

    Code:
    wstring name = wstring((wchar_t*)Buffer(buf, size).data());
    wcout << L"Name: " << name << endl
    When I thought I fixed the code as shown below, I realized that the first wcout worked, but all subsequent wcouts's did not. Any idea what I did wrong?

    Code:
    string sname= Buffer(buf, size);
    wstring name = wstring((wchar_t*)sname.data(), sname.size());
    wcout << L"Name: " << name << endl

  2. #2
    Join Date
    Jan 2009
    Posts
    1,689

    Re: string/wstring question

    data() does not guarantee either way about whether or not there is a null terminator, I've seen it both ways. MinGW for example, data() and c_str() are the same function, on GCC OSX, data() is almost never null terminated.

    Also, that is not how you convert strings to wstrings, this is:
    Code:
    string temp("I am a string");
    wstring temp2(temp.begin(), temp.end());

  3. #3
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: string/wstring question

    Quote Originally Posted by ekhule View Post
    Hello,

    I am having problems with string/wstring code. In the code below Buffer returns a string.

    This first code works, but I noticed that if the returned string from Buffer contained embedded null characters, it would terminate the string when passed to wstring.

    Code:
    wstring name = wstring((wchar_t*)Buffer(buf, size).data());
    wcout << L"Name: " << name << endl
    When I thought I fixed the code as shown below, I realized that the first wcout worked, but all subsequent wcouts's did not. Any idea what I did wrong?

    Code:
    string sname= Buffer(buf, size);
    wstring name = wstring((wchar_t*)sname.data(), sname.size());
    wcout << L"Name: " << name << endl
    What is "Buffer"? I do not know of any such type.

    strings have 2 constructors that take a (w)char*:

    Code:
    string(char* s);
    string(char* s, size_t n);
    The first one will initialize the strings with the characters located at s, and will stop at the first null character encountered.

    The second one will initialize the string with all n characters located at p, including null characters. The resulting string will be exactly n chars long.

    see here

    Depending on your requirements, you'll have to chose carefully between both forms.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  4. #4
    Join Date
    Mar 2009
    Posts
    166

    Re: string/wstring question

    Buffer is an internal function that returns a string. I'm well aware of the two different constructors for strings, hence why my second code block attempted to "fix" the null termination issue.

    Here is the exact problem is a small snippet of sample code. Does anyone know why the second wcout does not work?

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    string getstring()
    {
       wchar_t* temp=L"test!";
       string ret((char*)temp, 12);
       return ret;
    }
    
    int main()
    {
       // The first "test!" prints out
       string test = getstring();
       wstring name = wstring((wchar_t*)test.data(), test.size());
       wcout << L"Name: " << name << endl;
    
       // This second "test!" does not print out
       string test2 = getstring();
       wstring name2 = wstring((wchar_t*)test2.data(), test2.size()); 
       wcout << L"Name: " << name2 << endl;
    }
    Last edited by ekhule; May 4th, 2011 at 09:26 AM.

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449

    Re: string/wstring question

    Quote Originally Posted by ekhule View Post
    Here is the exact problem is a small snippet of sample code. Does anyone know why the second wcout does not work?
    wcout always works. There is nothing wrong with it, provided you send it data that is correct.

    Does test2 and name2 contain the correct information so that wcout "works"?

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Mar 2009
    Posts
    166

    Re: string/wstring question

    Hello Paul,

    Yes they do, which is why this is so confusing. Can I ask that you compile my code quickly and test? You'll see what I see then.

    Regards,
    Ellay K.

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449

    Re: string/wstring question

    Quote Originally Posted by ekhule View Post
    Hello Paul,

    Yes they do,
    How do you know this? You need to inspect the exact byte-sequence to determine if that is a valid wide string (terminated with double NULL), and the data is the same.

    They could not be the same -- why would wcout act differently if they are the same thing? You can verify it by carefully inspecting both strings, byte by byte.

    Regards,

    Paul McKenzie

  8. #8
    Join Date
    Mar 2009
    Posts
    166

    Re: string/wstring question

    Ok you are correct, they are different in the byte sequence. If I use the data() method to wcout it works as expected. For some reason sending the wstring to wcout breaks this code. Here is the code that works as expected now. It still however doesn't make sense to me.

    Code:
    #include <iostream>
    #include <string>
    using namespace std;
    
    string getstring()
    {
       wchar_t* temp=L"test!";
       string ret((char*)temp, 12);
       return ret;
    }
    
    int main()
    {
       string test = getstring();
       wstring name = wstring((wchar_t*)test.data(), test.size());
       wcout << L"Name: " << name.data() << endl;
    	
       string test2 = getstring();
       wstring name2 = wstring((wchar_t*)test2.data(), test2.size()); 
       wcout << L"Name: " << name2.data() << endl;
    }


    Regards,
    Ellay K.
    Last edited by ekhule; May 4th, 2011 at 10:46 AM.

  9. #9
    Join Date
    Mar 2009
    Posts
    166

    Re: string/wstring question

    I think the true error here is that I needed to divide the size of the string by 2 to pass to the wstring constructor.

    e.g.:
    Code:
       string test2 = getstring();
       wstring name2 = wstring((wchar_t*)test2.data(), test2.size()/2);
    since the wstring has mutlibyte chars. make sense?

    Regards,
    Ellay K.

  10. #10
    Join Date
    May 2002
    Posts
    1,435

    Re: string/wstring question

    Quote Originally Posted by ekhule View Post
    I think the true error here is that I needed to divide the size of the string by 2 to pass to the wstring constructor.

    e.g.:
    Code:
       string test2 = getstring();
       wstring name2 = wstring((wchar_t*)test2.data(), test2.size()/2);
    since the wstring has mutlibyte chars. make sense?

    Regards,
    Ellay K.
    No, it does not make sense. What you have done here is stumble upon a solution that just happens to work. You should never use code like this in a project. What you need to do is address the real source of the issues you are having: why are you mixing string and wstring in the same project? This is not something I, or anyone else here I assume, would do unless absolutely necessary.

    If you do find it necessary to mix string types, you can't do it by luck - you have to really know what you are doing. As I see it, the source of your problems is that you are coding primarily with wide strings and streams, but you have a single function, Buffer(), that returns string. Why? Is Buffer() a function that you wrote? If so, then you need to concentrate on that so it returns a string type compatible with the rest of your code. If not, then you may be forced to mix the string types - unless you are not telling us the whole story. For example, Buffer() may be part of a library that contains duplicate functions for string and wstring types and you are unaware of that fact.

    In short, please tell us why you find it necessary to mix string and wstring.

  11. #11
    Join Date
    Jan 2009
    Posts
    1,689

    Re: string/wstring question

    Your c cast is what's causing your problems. You can't cast a c_str to a wchar_t string like that unless you really know what it is doing at the byte level. Look at this:

    This is "HI", 48 is letter H, 49 is letter I, 00 is the null terminator, XX are out of bounds
    c_str: 48 49 00 XX XX XX XX XX

    this is (wchar_t*)c_str 484900XX XXXXXXXX


    Here is another example.
    Code:
    char* cstr = "hello\x00\x00\x00\x00";  // tagging on extra nulls to avoid crashes in this test
    wchar_t * wstr = (wchar_t*)cstr;
    cout << wcslen(wstr) << endl;
    What do you expect to be printed out? I promise you that it won't be 5, it'll be 2.


    You are misunderstanding how to cast between strings, please refer to my first post. If you only want half the string then:
    Code:
    string test("hello");
    wstring wtest(test.begin(), test.begin() + test.length() / 2);
    If you already have it in a string object, don't revert to c strings, use iterators, its the C++ way.
    Last edited by ninja9578; May 4th, 2011 at 04:58 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured