我有一个std::string
和一系列int
s。我想在 int
指示的位置之前添加字符。此操作应该就地执行。举个例子来考虑:
string: "abcde"
positions: 1, 3
character to be inserted: ' '
=> string after modification: "a bc de"
Algorithmwise,在O(n)时间内实现它没有问题,但我怀疑这已经在例如某处实现了。促进。但是,我找不到那里的实现。是否有提供此功能的C ++库?
答案 0 :(得分:1)
更新更新到包含就地操作要求的问题:
#include <algorithm>
#include <vector>
#include <cassert>
#include <array>
template <typename What>
void multi_insert(std::string& text, std::vector<size_t> positions, What const& insertion) {
using std::begin;
using std::end;
assert(std::is_sorted(positions.begin(), positions.end()));
auto source_n = text.length();
auto extension = insertion.size() * positions.size();
text.resize(text.length() + extension);
using Rit = std::string::reverse_iterator;
Rit dest_it = text.rbegin(),
source_it = dest_it + extension;
auto posit = positions.rbegin();
while (dest_it != source_it) {
assert(*posit <= source_n);
for (;source_n && *posit != source_n; --source_n)
*dest_it++ = *source_it++;
dest_it = std::copy(std::make_reverse_iterator(insertion.end()), std::make_reverse_iterator(insertion.begin()), dest_it);
++posit;
}
}
void multi_insert(std::string& text, std::vector<size_t> positions, char insertion = ' ') {
multi_insert(text, std::move(positions), std::array<char, 1> {{insertion}});
}
#include <iostream>
static size_t constexpr NONE = -1;
template <typename What>
void do_tests(What const& insertion) {
std::vector<size_t> p;
for (size_t a : { NONE, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul })
for (size_t b : { NONE, 0ul, 1ul, 2ul, 3ul, 4ul, 5ul })
{
if (b<a)
continue;
p.assign({a,b});
p.erase(std::remove_if(p.begin(), p.end(), [](auto n) { return n == NONE; }), p.end());
std::string text = "abcde";
multi_insert(text, p, insertion);
auto opt = [](size_t n) -> char { return n==NONE?'.':('0'+n); };
std::cout << opt(a) << " " << opt(b) << " Result: '" << text << "'\n";
}
}
int main() {
do_tests('!');
do_tests(std::string("***"));
}
打印
. . Result: 'abcde'
0 . Result: '!abcde'
0 0 Result: '!!abcde'
0 1 Result: '!a!bcde'
0 2 Result: '!ab!cde'
0 3 Result: '!abc!de'
0 4 Result: '!abcd!e'
0 5 Result: '!abcde!'
1 . Result: 'a!bcde'
1 1 Result: 'a!!bcde'
1 2 Result: 'a!b!cde'
1 3 Result: 'a!bc!de'
1 4 Result: 'a!bcd!e'
1 5 Result: 'a!bcde!'
2 . Result: 'ab!cde'
2 2 Result: 'ab!!cde'
2 3 Result: 'ab!c!de'
2 4 Result: 'ab!cd!e'
2 5 Result: 'ab!cde!'
3 . Result: 'abc!de'
3 3 Result: 'abc!!de'
3 4 Result: 'abc!d!e'
3 5 Result: 'abc!de!'
4 . Result: 'abcd!e'
4 4 Result: 'abcd!!e'
4 5 Result: 'abcd!e!'
5 . Result: 'abcde!'
5 5 Result: 'abcde!!'
. . Result: 'abcde'
0 . Result: '***abcde'
0 0 Result: '******abcde'
0 1 Result: '***a***bcde'
0 2 Result: '***ab***cde'
0 3 Result: '***abc***de'
0 4 Result: '***abcd***e'
0 5 Result: '***abcde***'
1 . Result: 'a***bcde'
1 1 Result: 'a******bcde'
1 2 Result: 'a***b***cde'
1 3 Result: 'a***bc***de'
1 4 Result: 'a***bcd***e'
1 5 Result: 'a***bcde***'
2 . Result: 'ab***cde'
2 2 Result: 'ab******cde'
2 3 Result: 'ab***c***de'
2 4 Result: 'ab***cd***e'
2 5 Result: 'ab***cde***'
3 . Result: 'abc***de'
3 3 Result: 'abc******de'
3 4 Result: 'abc***d***e'
3 5 Result: 'abc***de***'
4 . Result: 'abcd***e'
4 4 Result: 'abcd******e'
4 5 Result: 'abcd***e***'
5 . Result: 'abcde***'
5 5 Result: 'abcde******'
答案 1 :(得分:0)
我无法想到一个完全符合标准的标准实现,但您可以使用以下方法实现此目的:
int main() {
std::string input { "abcde" };
std::set<size_t> positions { 1, 3 };
char separator = ' ';
std::string output;
output.reserve(input.size() + positions.size()); // Make sure (at most) a single allocation is performed
unsigned index = 0;
auto pos = positions.begin();
for (auto & i : input)
{
if (pos != positions.end() && *pos == index)
{
output += separator;
++pos;
}
output += i;
++index;
}
std::cout << output << std::endl;
}
假设n
是输入字符串的长度,m
是位置矢量的长度,则执行:
O(n + m) [Allocation] + O(n + m) [Copy] = O(n + m) [Total]
。