0

Suppose I have this kind of string format:

"<RGB:255,0,0>this text is colored RED.<RGB:0,255,0> While this text is colored GREEN"; 

I want to extract the values inside the <RGB> i.e 255,0,0 and put it on other variables then delete the chars from '<' to '>'.

My code so far:

//this function is called after the loop that checks for the existence of '<' void RGB_ExtractAndDelete(std::string& RGBformat, int index, RGB& rgb) { int i = index + 5; //we are now next to character ':' std::string value; int toNumber; while (RGBformat[i] != ',') { value += RGBformat[i++]; } ++i; std::stringstream(value) >> toNumber; rgb.R = toNumber; value = ""; while (RGBformat[i] != ',') { value += RGBformat[i++]; } ++i; std::stringstream(value) >> toNumber; value = ""; rgb.G = toNumber; while (RGBformat[i] != '>') { value += RGBformat[i++]; } ++i; std::stringstream(value) >> toNumber; value = ""; rgb.B = toNumber; //I got the right result here which is //start: <, end: > printf("start: %c, end: %c\n", RGBformat[index], RGBformat[i]); //but fail in this one //this one should erase from '<' until it finds '>' RGBformat.erase(index, i); } 

If I put the <RGB:?,?,?> on the start of the string, it works but it fails when it finds it next to a non '<' character. Or can you suggest much better approach how to do this?

3
  • It fails when..? Can you clarify. Commented Jun 11, 2013 at 8:23
  • @Armin it fails on the second <RGB:?,?,?> Commented Jun 11, 2013 at 8:24
  • @Armin I mean, the deletion of the character fails when it didn't find first the '<' before any character. For example `A text<RGB:?,?,?>. Commented Jun 11, 2013 at 8:29

4 Answers 4

3
  1. Use std::str::find to locate the <RGB, :, , and >.
  2. Use std::str::substr to "cut out" the string.
  3. Add if (!std::strinstream(value)>> toNumber) ... to check that the number was actually accepted.

Something like this:

std::string::size_type index = std::RGBformat.find("<RGB"); if (index == std::string::npos) { ... no "<RGB" found } std::string::size_type endAngle = std::RGBformat::find(">", index); if (endAngle == std::string::npos) { ... no ">" found... } std::string::size_type comma = std::RGBformat.find(",", index); if (comma == std::string::npos && comma < endAngle) { ... no "," found ... } std::string value = RGBformat.substr(index, comma-index-1); std::stringstream(value) >> toNumber; value = ""; rgb.R = toNumber; std::string::size_type comma2 = std::RGBformat.find(",", comma+1); if (comma2 == std::string::npos && comma2 < endAngle) ... 

Note that this may look a bit clumsier than your current code, but it has the advantage of being a lot safer. If someone passed in "<RGB:55> .... " to your existing code, it would break, because it just keeps going until either you get bored and press a key to stop it, or it crashes, whichever comes first...

Sign up to request clarification or add additional context in comments.

1 Comment

I am not familiar with those functions. Can you please provide some examples for me? And also, how does std::stringstream behave exactly in terms of data types when it pass a string value to other primitive data type. As you can see in my code, I need to pass it first into an int before the unsigned chars. Thanks! I'm still not in my computer that's why I cannot check this one.
1

If you can use Boost or C++11, this is really the perfect place for regular expressions.

You can match your color specifiers with "\\<RGB:(\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\>" - or if you have C++11 raw string literals, you can write this more readably as R"rx(\<RGB:(\d{1,3}),(\d{1,3}),(\d{1,3})\>)rx".

Comments

0

Parse it with

std::getline 

http://en.cppreference.com/w/cpp/string/basic_string/getline

This function accepts a delimiter (e.g. '<' or '>') as third argument. For an example look at:

Basic C++ program, getline()/parsing a file

Comments

0

Here a modified code I use to extract text from html and retrieve data from html tag when I can't use regexp. Otherwise I advice you to use regular expressions they are much more easier to setup.

In my code I ended my tags with "</>" for the color "<RGB:255,0,0>My text</>".

Hope it would help!

#include <iostream> #include <string> #include <vector> #include <cstdlib> using namespace std; typedef struct{ string text; uint8_t r; uint8_t g; uint8_t b; }TextInfo; vector<TextInfo> vect; const vector<TextInfo> & extractInfos(const string & str){ string newStr = str; vect.clear(); do{ TextInfo info; int index = newStr.find('>'); if(index != -1 && newStr.find('<') == 0){ // We get "<RGB:r,g,b>" string color = newStr.substr(0,index+1); // We extract red color string red = color.substr(color.find(':') + 1, color.find(',') - color.find(':') - 1); // We get "g,b>" color = color.substr(color.find(',') + 1, color.length() - color.find(',')); // We extract green color string green = color.substr(0,color.find(',')); // We extract "b>" color = color.substr(color.find(',') + 1, color.length() - color.find('>')); // We get blue color; string blue = color.substr(0,color.find('>')); // string to int into a uint8_t info.r = atoi(red.c_str()); info.g = atoi(green.c_str()); info.b = atoi(blue.c_str()); // We remove the "<RGB:r,g,b>" part from the string newStr = newStr.substr(index+1,newStr.length()-index); index = newStr.find("</>"); // We get the text associated to the color just extracted info.text = newStr.substr(0,index); // We remove the "</>" that ends the color newStr = newStr.substr(index+3,newStr.length()-(index+2)); }else{ // We extract the string to the next '<' or to the end if no other color is set int i = newStr.find('<'); if(i == -1){ i=newStr.length(); } info.text = newStr.substr(0,i); info.r = 0; info.g = 0; info.b = 0; // No color then we put default to black // We get the new part of the string without the one we just exctacted newStr = newStr.substr(i, newStr.length() - i); } // We put the data into a vector vect.push_back(info); }while(newStr.length() != 0); // We do it while there is something to extract return vect; } int main(void){ vector<TextInfo> myInfos = extractInfos("<RGB:255,0,0>String to red</><RGB:0,255,0>Green string</>Default color string"); for(vector<TextInfo>::iterator itr = myInfos.begin();itr != myInfos.end();itr++){ cout << (*itr).text << endl; } return 0; } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.