-
May 4th, 2011, 07:52 AM
#1
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
-
May 4th, 2011, 08:08 AM
#2
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());
-
May 4th, 2011, 08:36 AM
#3
Re: string/wstring question
Originally Posted by ekhule
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.
-
May 4th, 2011, 08:51 AM
#4
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.
-
May 4th, 2011, 10:01 AM
#5
Re: string/wstring question
Originally Posted by ekhule
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
-
May 4th, 2011, 10:16 AM
#6
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.
-
May 4th, 2011, 10:24 AM
#7
Re: string/wstring question
Originally Posted by ekhule
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
-
May 4th, 2011, 10:37 AM
#8
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.
-
May 4th, 2011, 12:52 PM
#9
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.
-
May 4th, 2011, 02:53 PM
#10
Re: string/wstring question
Originally Posted by ekhule
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.
-
May 4th, 2011, 04:52 PM
#11
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
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|