Как извлечь и удалить символы в std :: string

Предположим, у меня есть такой формат строки:

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

Я хочу извлечь значения внутри <RGB> то есть 255,0,0 и поместите его в другие переменные, затем удалите charс из '<' в '>',

Мой код до сих пор:

//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:?,?,?> в начале строки, это работает, но не удается, когда он находит его рядом с не ‘<‘ персонаж. Или вы можете предложить гораздо лучший подход, как это сделать?

0

Решение

  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> .... " к вашему существующему коду, он сломается, потому что он просто продолжает работать, пока вам не надоест и не нажмете клавишу, чтобы остановить его, или он рухнет, в зависимости от того, что произойдет раньше …

3

Другие решения

Если вы можете использовать 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",

1

Разбери это с

std::getline

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

Эта функция принимает разделитель (например, ‘<‘или’> ‘) в качестве третьего аргумента.
Для примера посмотрите на:

Базовая программа на C ++, getline () / парсинг файла

0

Здесь измененный код, который я использую для извлечения текста из HTML и извлечения данных из тега HTML, когда я не могу использовать регулярное выражение. В противном случае я советую вам использовать регулярные выражения, их гораздо проще настроить.

В моем коде я закончил свои теги с «</>»за цвет»<RGB: 255,0,0>Мой текст</>».

Надеюсь, это поможет!

#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;
}
0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector