Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

regex - C++ Compare and replace last character of stringstream

I would like to check the following:

  1. If the last character appended to the stringstream is a comma.
  2. If it is remove it.

std::stringstream str;
str << "["
//loop which adds several strings separated by commas

str.seekp(-1, str.cur); // this is to remove the last comma before closing bracket

str<< "]";

The problem is if nothing is added in the loop, the opening bracket is removed from the string. So I need a way to check whether the last character is a comma. I did that like this:

if (str.str().substr(str.str().length() - 1) == ",")
{
    str.seekp(-1, rteStr.cur);
}

But I don't feel very good about this. Is there a better way to do this?

About the loop:

Loop is used to tokenize a set of commands received through sockets and format it to send to another program through another socket. Each command ends with an OVER flag.

std::regex tok_pat("[^\[",\]]+");
std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
std::sregex_token_iterator tok_end;
std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);
while (baseStr == "OVER")
{
    //extract command parameters
    str << "extracted_parameters" << ","
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

The way I often deal with these loops where you want to put something like a space or a comma between a list of items is like this:

int main()
{
    // initially the separator is empty
    auto sep = "";

    for(int i = 0; i < 5; ++i)
    {
        std::cout << sep << i;
        sep = ", "; // make the separator a comma after first item
    }
}

Output:

0, 1, 2, 3, 4

If you want to make it more speed efficient you can output the first item using an if() before entering the loop to output the rest of the items like this:

int main()
{
    int n;

    std::cin >> n;

    int i = 0;

    if(i < n) // check for no output
        std::cout << i;

    for(++i; i < n; ++i) // rest of the output (if any)
        std::cout << ", " << i; // separate these
}

In your situation the first solution could work like this:

    std::regex tok_pat("[^\[",\]]+");
    std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
    std::sregex_token_iterator tok_end;
    std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);

    auto sep = ""; // empty separator for first item

    while (baseStr == "OVER")
    {
        // extract command parameters
        str << sep << "extracted_parameters";
        sep = ","; // make it a comma after first item
    }

And the second (possibly more time efficient) solution:

    std::regex tok_pat("[^\[",\]]+");
    std::sregex_token_iterator tok_it(command.begin(), command.end(), tok_pat);
    std::sregex_token_iterator tok_end;
    std::string baseStr = tok_end == ++tok_it ? "" : std::string(*tok_it);

    if (baseStr == "OVER")
    {
        // extract command parameters
        str << "extracted_parameters";
    }

    while (baseStr == "OVER")
    {
        // extract command parameters
        str << "," << "extracted_parameters"; // add a comma after first item
    }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...