Reputation: 79
This is in a way related to my other question.
My task is to take last times
characters of string str
and add them to string removed
, and to remove those characters from str
.
My idea was to do one memory allocation, iterate over times
characters of str
one time. That's what I am doing in the code below, assigning to removed
index by index and popping from str
per
iteration.
int times = std::stoi(arg); // arg is const std::string &
std::string removed;
removed.resize(times);
while (times > 0)
{
removed[times-1] = str.back();
str.pop_back();
--times;
}
Question: what is the most efficient (without excessive copying, iterating several times, etc.) and elegant way to do this?
Upvotes: 1
Views: 203
Reputation: 117298
I'd probably use substr
and resize
:
if(str.size() >= times) {
std::string removed = str.substr(str.size() - times);
str.resize(str.size() - times);
}
Then again, if you don't actually need the resulting strings to be mutable, a very efficient approach would be to create std::string_view
s over the original str
and leave str
unchanged. std::string_view
s are really cheap. They typically consist of only a pointer and a length and doesn't do any dynamic memory allocation. Note though that str
must "outlive" the views since it's str
that owns the actual memory.
if(str.size() >= times) {
std::string_view vStr(str.begin(), str.end() - times);
std::string_view vRemoved(str.end() - times, str.end());
std::cout << vStr << '\n';
std::cout << vRemoved << '\n';
}
Upvotes: 3
Reputation: 180500
I would do some checking before hand to make sure times <= str.size()
but as long as it is this can be done pretty simple using append
and erase
like
removed.append(str.end() - times, str.end()); // adds the end of str to removed
str.erase(str.end() - times, str.end()); // removes the end from str
Upvotes: 4