开发者

Erasing numbers from beginning and end of std::string

开发者 https://www.devze.com 2023-01-08 21:47 出处:网络
Would there be a better w开发者_运维百科ay to do this using alogrithm functions like std::find()?

Would there be a better w开发者_运维百科ay to do this using alogrithm functions like std::find()?

std::string s = "012X012Y012";

//After erasing the numbers from beginning and end; the end result should be X012Y

size_t index = s.find_first_not_of("0123456789");
string::iterator iter_end = s.begin();
advance(iter_end, index);
s.erase(s.begin(), iter_end);

//Now std::string should be X012Y012

size_t index = s.find_last_not_of("0123456789")+1;
string::iterator iter_start = s.begin();
advance(iter_start, index);
s.erase(iter_start, s.end());

//Finally, std::string should be X012Y


Seems fine enough. I'd factor out your constant:

const std::string Numbers = "0123456789";

And re-use that. erase does allow you to use indices instead of iterators, so you can trim all that iterator stuff from your code. You should also check the results of your search, otherwise you'll do weird things to your string:

std::size_t start = s.find_first_not_of(Numbers);
if (start != std::string::npos)
    s.erase(0, start);

size_t end = s.find_last_not_of(Numbers);
if (end != std::string::npos)
    s.erase(end + 1, std::string::npos);

Lastly, I think you should trim the right before the left. If you trim the left first, during erase the remainder of the string needs to be copied and moved down. By trimming the right first, you eliminate some things to copy. Nothing major, I suspect, but might as well.

(This is true of most sequence containers: erasing from some point to the end simply means getting rid of objects, while erasing from the start to some point requires moving the remaining items into their new spot.)


Of course, you can generalize this and re-use it:

// typically you trim whitespace, so for the sake of
// a generic utility, default to that
const std::string whitespace = " \f\n\r\t\v";

void trim_left(std::string& pStr, const std::string& pExcess = whitespace)
{
    std::size_t start = s.find_first_not_of(pExcess);
    if (start != std::string::npos)
        s.erase(0, start);
}

void trim_right(std::string& pStr, const std::string& pExcess = whitespace)
{
    size_t end = s.find_last_not_of(pExcess);
    if (end != std::string::npos)
        s.erase(end + 1, std::string::npos);
}

void trim(std::string& pStr, const std::string& pExcess = whitespace)
{
    // right then left, for reasons said above
    trim_right(pStr, pExcess);
    trim_left(pStr, pExcess);
}


Not a pure STL solution, but the Boost String libraries make this trivial:

std::string s = "012X012Y012";
boost::trim_if(s, boost::is_digit());
std::cout << s << std::endl; // Outputs: "X012Y"
0

精彩评论

暂无评论...
验证码 换一张
取 消