   std::string problem with copying characters[Solved]
  I think im doing this really wrong, what I want to do is grab a string use a function to determine the pixel length the string would be if I was to print it out, loop through the end of the string copying 1 character a time until its less than my space that holds the text.I used to do this using char but its a ton of code.. I wrote this code to try to get it to working using strings but it just ends up going into a infinite loop because its not erasing the character I want it to...GetSizeForString accepts a string and returns a int with the pixel value (right side) that the string takesAny help would be greatly appreciated =pbool ChatBox::AddChat(string Mychat){int TextSize=GetSizeForString(Mychat); //this is the size in the X direction that our text will take upbool MoreLines = false; //true if we have more than 1 line from that line of textstring NewString; //this is the string we build up out of the first string's overflowwhile(TextSize > bottomrightx)//if its greater than our window we need to add it to a new line{TextSize = GetSizeForString(Mychat);//get the text size we would output in pixelsNewString.append(Mychat.c_str()-1);//move the last character to a new stringMychat.erase(Mychat.end()); //erase that character at the endMoreLines = true;}//after this breaks the stuff left in Mychat should fit on one line so we can display itif (MoreLines) //if we had more lines add that string to our buffer{AddChat(NewString); //add the rest of our string as a new text}if (MyChatData.size() > MAX_CHAT_SIZE){MyChatData.pop_back(); //kill our first element}MyChatData.push_front(new ChatData(Mychat)); //add it to our listUpdateChat=true; //make sure we draw it next loopreturn true;};[Edited by - yewbie on May 25, 2009 3:25:24 PM]
  First, don't do this:Mychat.c_str()-1It's not doing what you think it's doing.  c_str() returns a pointer to the beginning of a null-terminated character sequence.  Meaning it points to the beginning of the C-style string.  By subtracting 1 from it, you are moving that pointer back one byte so that it now points to some invalid piece of memory outside of the safe chunk of memory (the safe chunk of memory is the chunk of memory holding the C-style string).  Which means that it's undefined behavior.Then you go ahead and try to append this entire C-style string to NewString.  That's bad, because not only does the pointer point to invalid memory that you shouldn't be accessing, you are also (probably) appending a whole lot more than just one character.  If you want to access the last character in a string, just do Mychat[Mychat.length() - 1] (assuming it isn't empty, if it is, that'll cause problems).Also, your erase method is wrong.  end() returns an iterator  referring to the next element after the last character in the string.  Meaning that the iterator doesn't refer to part of the string, it refers past the string.  Either properly use the erase method or use the resize method (and call Mychat.resize(Mychat.length() - 1), assuming it isn't empty).Here's some mandatory reading:c_str()appendopeator+=operator[]end()resizestringAlso, I'm pretty sure your method is going to end up reversing part of your string if it calls itself again because you take off the last character in Mychat and then add it to the end of NewString.  For example, if MAX_CHAT_SIZE is 6 and your string is "Hello World", it'll end up looking like this:dlroW HelloOr maybeHellodlroW depending on how you render it.   ;  Thanks for your reply, I will give it some reading, I figured I would be able to just wing it, bad idea on my part =p   ;  I was able to get it working with your suggestions and reading up on strings, I was also able to combat the reverse string on the new line by making a new string copying the old string to the new string, copying the new character to the old string, then appending the new string to the old stringbool ChatBox::AddChat(string Mychat){int TextSize=GetSizeForString(Mychat); //this is the size in the X direction that our text will take upbool MoreLines = false; //true if we have more than 1 line from that line of textstring NewString; //this is the string we build up out of the first string's overflowwhile(TextSize > bottomrightx - 30)//if its greater than our window we need to add it to a new line{TextSize = GetSizeForString(Mychat);//get the text size we would output in pixelsstring test;test += Mychat[Mychat.length()-1];//move the last character to a new stringtest += NewString;NewString = test;Mychat.resize(Mychat.length() - 1); //erase that character at the endMoreLines = true;}//after this breaks the stuff left in Mychat should fit on one line so we can display itif (MyChatData.size() > MAX_CHAT_SIZE){MyChatData.pop_back(); //kill our first element}MyChatData.push_front(new ChatData(Mychat)); //add it to our listif (MoreLines) //if we had more lines add that string to our buffer{AddChat(NewString); //add the rest of our string as a new text}UpdateChat=true; //make sure we draw it next loopreturn true;};;  Good to see the changes!  Let's work on that algorithm though.  It's not nearly as efficient or clean as it could be.  It would be much more efficient if you started at the beginning of the string and worked one character at a time.  But it depends on how your GetSizeForString function works.  Does it parse Unicode or ASCII characters?  Because writing the code depends on whether your text is ASCII or Unicode encoded.  I assume it's ASCII you're dealing with because of how you're removing the last character from the string.  But here's a simplified version:1) Start with the first character of the string2) Find the width of that character3) If the current line is empty but the character's width exceeds the size of the text box containing it, do something about it (I don't know how you'd handle this, it's up to you)4) If the current line is not empty but the character's width + the current line's width exceeds the size of the text box containing it, start a new line and add the character to the new line, then advance to the next character and go back to step 2)5) If the current line's width + the character's width fits within the text box containing it, add the character to the current line's text, advance to the next character, and go back to step 2)If you want to break up the text according to each word (separated by white space, like a space, tab, or new line), then you'll just have to change a little how you add things to the current/next line.  Also note that if you are at the last character in the string in steps 3, 4, or 5, just break out rather than trying to advance to the next character (which doesn't exist).  This algorithm I'm talking about runs in O(n) time.  The main problem with your current algorithm is that it runs in approximately O(n2) time (assuming I did the analysis correctly) because it repeatedly finds the length of the Mychat, decreasing it only 1 character at a time, and then it recurses and does the same, semi-redundant thing.Oh, and just so you know, rather than doing this:string test;test += Mychat[Mychat.length()-1];//move the last character to a new stringtest += NewString;NewString = test;You could just do this:NewString = Mychat[Mychat.length()-1]' + NewString;Because of good old operator+.   ;  GetSizeForString uses a windows function to return how much pixels a string will take if used in drawtext here is what I wroteint ChatBox::GetSizeForString(string MyString){HDC hdc;SIZE sz;lpddsChat->GetDC(&hdc);//attach our Chat Surface to a hdcGetTextExtentPoint32(hdc,MyString.c_str(),strlen(MyString.c_str()),&sz);lpddsChat->ReleaseDC(hdc);return sz.cx; //return the x value}I have to use this because with draw text you don't know the individual size of each text for instancewwwiii and iwiwiwi which have the same characters take up a different ammount of space.Quote:You could just do this:NewString = Mychat[Mychat.length()-1]' + NewString;Because of good old operator+.This looks great!, yeah I have some code to word wrap (I have not implemented it yet its just in planning stages), but basically if its > than our farthest extent we can draw to it will recurse back to the first white space, then copy everything after that instead.   ;  Cool, sounds good.  It would be interesting to see your final solution.  And just one last, quick tip: you should use MyString.length() instead of strlen(MyString.c_str()) :)   ;  Update: I did get word wrap working!I could not get this line to work no matter what, the string + fucntion would not determine what Mychat[Mychat.length()-1] when used with = (oh well)NewString = Mychat[Mychat.length()-1] + NewString;but here is my full working solutionbool ChatBox::AddChat(string Mychat){int TextSize=GetSizeForString(Mychat); //this is the size in the X direction that our text will take upbool MoreLines = false; //true if we have more than 1 line from that line of textstring NewString; //this is the string we build up out of the first string's overflowstring test; //this is a temporary string inside of our loopbool needtogetlastspace = false;while( (TextSize > bottomrightx - 35) || needtogetlastspace==true)//if its greater than our window we need to add it to a new line{needtogetlastspace = true;//make sure we keep looping untill spaceTextSize = GetSizeForString(Mychat);//get the text size we would output in pixelstest.clear();test += Mychat[Mychat.length()-1];//move the last character to a new stringtest += NewString; //add our current string on to thatNewString = test; //copy our rebuilt string back to NewStringMychat.resize(Mychat.length() - 1); //erase that character at the endif (TextSize < bottomrightx - 35)//if we are going to break out after this loop{//keep recursing untill we get to a space since we are possibly halfway through a wordif (Mychat[Mychat.length()-1] == ' '){ //found our white space break outneedtogetlastspace = false; //we got itMoreLines = true;}}}//after this breaks the stuff left in Mychat should fit on one line so we can display itif (MyChatData.size() > MAX_CHAT_SIZE){MyChatData.pop_back(); //kill our first element}MyChatData.push_front(new ChatData(Mychat)); //add it to our listif (MoreLines) //if we had more lines add that string to our buffer{AddChat(NewString); //add the rest of our string as a new text}UpdateChat=true; //make sure we draw it next loopreturn true;};here is a screenshot in action;  I did fine one problem, if my string does not have a space in it and the size im sending to the next line is greater than a whole line...I wrote a bit of code to add a space at the end so it doesn't go into a massive never ending loop of adding the string seeing its too big and adding the string..But for the life of me I cannot get it to work...Edit: the error im getting with this code is std::out_of_rangestill working with it seeing where I went wrongsize_t found;found=NewString.find(' '); //check our new string for a spaceif (found==string::npos) //no space found we need to break it so its less than a whole new line{if (GetSizeForString(NewString) > bottomrightx - 35) //if our new string is going to be greater than a whole line but has no space{//we need insert a space after a whole linefor(int i=0;i<NewString.length();i++) //loop through our string and find out where to insert our space{newtest.clear();newtest.insert(0,NewString,0,i); //append to our string from the start to where we are at in the stringif (GetSizeForString(newtest) < bottomrightx - 35) //if it will fit add our space{NewString.insert(i-1," "); //insert a space at position i - 1needtogetlastspace = false; //we got it //break out of our loopMoreLines = true; }  }    }    }EDIT EDIT EDIT: I have no idea what is going wrong, I can't figure it out it seems to be going into a infinite loop[Edited by - yewbie on May 25, 2009 12:25:54 PM];  I broke this particular problem away from this big function so its easier to work with so basically if it finds a string that is longer than our chat box but has no space to break it up for word wrap it sends it to this function to deal with, I should have a easier time breaking it down now, updates to come   