0

假设我有这种字符串格式:

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

我想提取<RGB>ie 255,0,0 中的值并将其放在其他变量上,然后从to中删除chars 。'<''>'

到目前为止我的代码:

//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);

}

如果我把它<RGB:?,?,?>放在字符串的开头,它可以工作,但是当它在非'<'字符旁边找到它时它会失败。或者你能建议更好的方法来做到这一点吗?

4

4 回答 4

3
  1. 用于std::str::find定位<RGB、和。:_,>
  2. 用于std::str::substr“剪切”字符串。
  3. 添加if (!std::strinstream(value)>> toNumber) ...以检查该号码是否被实际接受。

像这样的东西:

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)
 ...

请注意,这可能看起来比您当前的代码有点笨拙,但它的优点是更安全。如果有人传入"<RGB:55> .... "您现有的代码,它会中断,因为它会一直运行,直到您感到无聊并按下一个键来停止它,或者它崩溃,以先到者为准......

于 2013-06-11T08:27:33.140 回答
1

如果可以使用 Boost 或 C++11,这确实是正则表达式的完美场所。

您可以将颜色说明符与"\\<RGB:(\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\>"- 匹配,或者如果您有 C++11 原始字符串文字,则可以将其编写为R"rx(\<RGB:(\d{1,3}),(\d{1,3}),(\d{1,3})\>)rx".

于 2013-06-11T09:22:56.110 回答
0

解析它

std::getline

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

此函数接受分隔符(例如“<”或“>”)作为第三个参数。例如看:

基本 C++ 程序,getline()/解析文件

于 2013-06-11T08:41:26.640 回答
0

这是一个修改后的代码,当我不能使用正则表达式时,我用来从 html 中提取文本并从 html 标记中检索数据。否则,我建议您使用正则表达式,它们更容易设置。

在我的代码中,我用“</>”结束了我的标签,颜色为“<RGB:255,0,0>My text</>”。

希望它会有所帮助!

#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;
}
于 2013-06-11T10:02:47.197 回答