🔒 Locked
std::string bug?
Advertisement
Original Post
Hello, is it possible to have a string containing the '\x00' character without it thinking that its the end of the string. For example, I want to have some data after the '\x00' character such as "\xFF\xFF\xFF\xFF\x00\xFF".
What problems did you encounter? Using G++, I can put null characters in my strings without any effort.
Quote:
MSDN page:
Objects of type string belonging to the C++ template class basic_stringare not necessarily null terminated. The null character ' \0 ' is used as a special character in a C-string to mark the end of the string but has not special meaning in an object of type string and may be a part of the string just like any other character.
a stl string does not have to be terminated by the \x00 character, but then you do actually have to tell it what size it should be.
String processing functions are mostly by nature null terminated, so erm I suppose it really depends on what you are planning to do with that string.
String processing functions are mostly by nature null terminated, so erm I suppose it really depends on what you are planning to do with that string.
And if it does give you trouble there's a nift container std::vector that would work just fine without any second thoughts about it.
Oh, and null terminated strings really are crap for many many things, when doing heavy stringwork they simply are among the worst there is.
Oh, and null terminated strings really are crap for many many things, when doing heavy stringwork they simply are among the worst there is.
The problem is most likely that you tried to assign it from a string literal. You can't stick \0 in a string literal; the assignment will think it's the end of the string. If you do mystring = std::string(string_with_nulls,length) instead of mystring = string_with_nulls it will work fine. If you have nulls in the string you also can't use the c_str member function.
Thanks for all of your replies, passing the length as an argument worked but how would I be able to get the length of the big strings that change all the time?
Quote:
Original post by ToohrVyk Quote:
Original post by paulecoyote
a stl string does not have to be terminated by the \x00 character, but then you do actually have to tell it what size it should be..std::string foo = "foo";foo[1] = '\0';
Now foo is the string made of the characters f, \0, o (in that order).
I meant if you used strcpy or something like that that uses null terminating characters as a stop. What you've done there is declare something with 3 elements and change the 2nd one, so that is bound to work.
Quote:
Original post by paulecoyote
I meant if you used strcpy or something like that that uses null terminating characters as a stop. What you've done there is declare something with 3 elements and change the 2nd one, so that is bound to work.
Then the obvious solution is to not use the functions in the cstring header and use std::string's many member functions or algorithms that are iterator aware. For example, why use strcpy when you are working with std::string? std::string has a perfectly usable copy constructor and assignment operator.
*sigh* Code:
Edit - updated to more comprehensive example
As you see (and probably know) SiCrane, when you have nulls embedded in a c-style string using the std::string copy constructor still does not copy across the whole string. I was assuming from the original post that he was assigning c-style strings to a std::string
Copying between different instances of std::strings though is of course a whole different kettle of herring [wink] OP, being that they are alot smarter then c-style strings.
[Edited by - paulecoyote on August 3, 2005 3:06:28 AM]
const char* testString=("abcd\x00 efghijk"); cout << "testString: " << testString << endl; std::string nullTest(testString); if (4==nullTest.length()) { cout << "Well looks like only the first bit of the string was copied across, just like I was trying to say all along: " << nullTest << endl; } else { cout << "All the string was copied, my bad." << endl; } std::string nullTest2; nullTest2.resize(13); nullTest2.assign( testString, 13); if ((13==nullTest2.length()) && ('k'==nullTest2[12])) { cout << "Well looks like the whole string was copied this time, because you told it what size it should be and used assign to tell it how many characters to copy: " << nullTest2 << endl; } else { cout << "Not all the string was copied, my bad." << endl; }Edit - updated to more comprehensive example
As you see (and probably know) SiCrane, when you have nulls embedded in a c-style string using the std::string copy constructor still does not copy across the whole string. I was assuming from the original post that he was assigning c-style strings to a std::string
Copying between different instances of std::strings though is of course a whole different kettle of herring [wink] OP, being that they are alot smarter then c-style strings.
[Edited by - paulecoyote on August 3, 2005 3:06:28 AM]
Quote:
Original post by kristoferos
Thanks for all of your replies, passing the length as an argument worked but how would I be able to get the length of the big strings that change all the time?
Err good question. The windows system represents the environment variable block as null terminated strings, and the end of the block with two null terminating characters next to each other. This lends itself to looping until you come across that double null marker. But doesn't work if your data has that marker in the body.
This is more about storage strategy and depends on your data... for example you may want to write away how many characters are in the string first, then follow it with the string itself. May be something like "5\tabcdef" where 5 is how many characters to expect, the tab is thrown away (and marks the end of the number) and the rest that follows is the 5 characters.
Quote:
Original post by paulecoyote
*sigh* Code:
All that code proves is that you don't understand the term "copy constructor". A copy constructor is a constructor for a class X that takes as an argument a cv qualified reference to X. That's it, no other constructor for a class X is a copy constructor.
Devja already posted the correct way to create a std::string from a non-null terminated pointer to a char array. My statement was directed exclusively at your post about the strcpy() function, which still stands.
Quote:
Original post by SiCrane Quote:
Original post by paulecoyote
*sigh* Code:
All that code proves is that you don't understand the term "copy constructor". A copy constructor is a constructor for a class X that takes as an argument a cv qualified reference to X. That's it, no other constructor for a class X is a copy constructor.
Devja already posted the correct way to create a std::string from a non-null terminated pointer to a char array. My statement was directed exclusively at your post about the strcpy() function, which still stands.
changed the one line to use the copy constructor, rather then just the constructor. Code still has same output.
const char* testString=("abcd\x00 efghijk"); cout << "testString: " << testString << endl; std::string nullTest; // Just for SiCrane nullTest = (testString); if (4==nullTest.length()) { cout << "Well looks like only the first bit of the string was copied across, just like I was trying to say all along: " << nullTest << endl; } else { cout << "All the string was copied, my bad." << endl; } std::string nullTest2; nullTest2.resize(13); nullTest2.assign( testString, 13); if ((13==nullTest2.length()) && ('k'==nullTest2[12])) { cout << "Well looks like the whole string was copied this time, because you told it what size it should be and used assign to tell it how many characters to copy: " << nullTest2 << endl; } else { cout << "Not all the string was copied, my bad." << endl; }Quote:
Original post by paulecoyote but then you do actually have to tell it what size it should be.
... which Deyja followed up with a concrete example (telling it how many characters where in the source string, IE tell it what size it should be:
Quote:
Original post by Deyjastd::string(string_with_nulls,length)
Quote:
Original post by kristoferos Thanks for all of your replies, passing the length as an argument worked
So we are agreed that the correct way is to tell pass an stl string how many characters it is expecting for a string with nulls embedded, right - though whatever method (construction, resizing, whatever).
Quote:
Original post by SiCranestd::string has a perfectly usable copy constructor and assignment operator.
But I stand by what I was saying in that passing a c-style string to an stl string copy contructor with null terminating characters in won't work, as that code fragment was trying to illustrate.
As for the strcpy stuff I meant processing before it's handed over to the stl string, as you say it isn't very advisable to use that stuff on a stl string. Because in context of the original posters problem, he seems to be reading things in from somewhere else then putting them in the string.
Quote:
Original post by paulecoyote
changed the one line to use the copy constructor, rather then just the constructor. Code still has same output.
You still either don't seem to grasp that a char * is not a std::string or you still don't grasp what a copy constructor is. You are still not calling a copy constructor, in fact you are even farther from calling a copy constructor because you are calling an assignment operator. Let me repeat: a copy constructor for an object X is a constructor that takes a cv qualified reference to X. That's it. Constructing a string from a char * is not copy construction. Only constructing a std::string from a std::string is copy construction.
Quote:
But I stand by what I was saying in that passing a c-style string to an stl string copy contructor with null terminating characters in won't work, as that code fragment was trying to illustrate.
Which, you don't seem to understand, no one is debating. (Edit: aside from the fact that you insist on calling it a copy constructor when it isn't.)
[Edited by - SiCrane on August 3, 2005 9:42:43 AM]
Quote:
Original post by paulecoyote
As you see (and probably know) SiCrane, when you have nulls embedded in a c-style string using the std::string copy constructor still does not copy across the whole string.
Yes it does. The C string ends at the first '\0' you put in there. The subsequent characters are not part of the string.
Of course, it does not copy the characters you put after the '\0', which are not part of the string, but are part of the character array.
Quote:
changed the one line to use the copy constructor, rather then just the constructor. Code still has same output.
I'm sorry, but you're not using a copy constructor in there.
std::string a( 10, '\0' );std::string b(a); // copy constructorstd::string c = "foo!";c = a; // assignment operatorin the above example, a contains only '\0' characters. Still, the copy constructor and assignment operation both conserve all 10 of these '\0' characters. Something which strcpy wouldn't, which was precisely SiCrane's point.
ah bollocks. Fine. So I slightly messed up my terminology *again* with a crappy example that I'm sick to the teeth of now that I was doing to illustrate a point when I should have probably been doing something else anyway. Obviously I'm just like the crappest coder ever. Perhaps I should be shot. Or hung. Geeze I was just trying to help and I'm getting picked on. Sometimes I wonder why I bother posting, it's obviously all rubbish anyway.
if you change that bloody line to
std::string nullTest = (testString);
it still compiles with the same result, because of the null teminating thingy there and that's all I was trying to get across. Which I think everyone agrees on anyway. So I don't know why I'm wound up. Sometimes I can *really* understand why people smoke pot. And why I shouldn't come here in the daytime.
const char* testString=("abcd\x00 efghijk");//Constructor. It's got a parameter. Wooooooo doggystd::string arse(testString);//Copy constructor, different from an assignment because the = sign is used at time of declarationstd::string biting = testString;//Default constructor. Default cos there's nothing there.std::string hussies;//Overridden assignment. It's different from the copy constructor. It's an implementation of =hussies = testString;if you change that bloody line to
std::string nullTest = (testString);
it still compiles with the same result, because of the null teminating thingy there and that's all I was trying to get across. Which I think everyone agrees on anyway. So I don't know why I'm wound up. Sometimes I can *really* understand why people smoke pot. And why I shouldn't come here in the daytime.
paulecoyote: I can see what you've been saying, but your last post is still incorrect:
The point SiCrane has been trying to make is that once you have your null-containing text inside a string you can deal with it safely and easily:
Enigma
const char* cStyleString=("abcd\x00 efghijk");//Constructor: std::string(char const *)std::string string(cStyleString);//Not a copy-constructor. Exactly the same as the above constructor: std::string(char const *)std::string string2 = cStyleString;//Default constructor: std::string()std::string string3;//Assignment operator: std::string & operator=(char const *)string3 = cStyleString;//Copy constructor: std::string(std::string const &)std::string string4(string2);//Copy constructor. Same as above: std::string(std::string const &)std::string string5 = string2;//Copy assignment operator: std::string & operator=(std::string const &)string5 = string3;The point SiCrane has been trying to make is that once you have your null-containing text inside a string you can deal with it safely and easily:
std::string initialString("Hello.\0Goodbye.\0Hello", 21);std::string appendedString = initialString + " again.";// appendedString = "Hello.\0Goodbye.\0Hello again."appendedString.replace(appendedString.find("Goodbye"), 7, "Farewell");// appendedString = "Hello.\0Farewell.\0Hello again."std::cout << appendedString << '\n';// prints "Hello.\0Farewell.\0Hello again.\n"Enigma
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement