提问人:Sonny 提问时间:7/19/2023 最后编辑:Vlad from MoscowSonny 更新时间:7/19/2023 访问量:149
如何使用字符串的原始索引来擦除单个字符?
How to use original index of a string to erase single character?
问:
假设我有一个字符串“abcd”和一个向量 [4,1,3,2] 来索引字符串。例如,vector 的第一个元素是 4,所以我应该删除“abcd”中的第 4 个字符,它指的是“d”。那么 vector 的第二个元素是 1,所以我应该删除“abcd”中的第一个字符,它指的是“a”,依此类推。每次删除一个字符时,我都想记录操作的字符串。这是我的代码:
# include <iostream>
# include <vector>
using namespace std;
int main()
{
int m;
cin >> m;
string T;
cin >> T;
cout << T << endl;
vector<int> arr(m);
for(auto &x : arr) cin >> x;
// Remove character from string at given index position
for (int i = 0; i < m; i++){
T.erase(T.begin() + arr[i]-1);
cout << T << endl;
}
return 0;
}
但是,我在输出中遇到了一些问题,我该如何解决它?
4
abcd
abcd
4 1 3 2
abc
bc
Segmentation fault
答:
将原始字符串中字符的索引与更新字符串中相同字符的索引混淆。
考虑字符串和擦除位置和字符(索引从 0 开始)。然后,首先删除第一个字符并拥有新字符串。现在,您不能再删除索引处的字符,因为没有字符。原始字符串中处于位置的字符现在位于索引处。ab
0
1
b
1
b
1
0
正如评论中提到的,最简单的方法是保持原始字符串不变,这样你就可以使用它的索引,并在一个单独的向量中跟踪“删除的”索引:
std::vector<bool> removed_chars(T.size());
for (size_t i = 0; i < arr.size(); i++){
removed_chars[ arr[i] ] = true; // "remove" the next char
for (size_t j = 0; j < T.size(); j++) {
if (! removed_chars[ j ]) std::cout << T[j]; // print the char if it is not removed yet
std::cout << "\n";
}
}
请注意,我假设输入使用从 0 开始的索引。如果输入使用从 1 开始的索引,我会在接受输入时尽早更正。
首先,C++ 中的索引从 .因此,如果您遵循此约定会更好。也就是说,带有索引的向量应包含以下序列,而不是 .0
{ 3, 0, 2, 1 }
{ 4, 1, 3, 2 }
一个简单的方法可以如下所示。要正确确定字符串中的索引,您需要检查字符串中有多少元素已被小于 currect 索引的索引擦除。
这是一个演示程序。
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<size_t> v = { 3, 0, 2, 1 };
std::string s( "abcd" );
for (size_t i = 0; i < v.size(); i++)
{
auto n = std::count_if( std::begin( v ), std::next( std::begin( v ), i ),
[=]( const auto &item ) { return item < v[i]; } );
s.erase( v[i] - n, 1 );
std::cout << s << '\n';
}
}
程序输出为
abc
bc
b
如果你在相关索引处标记字符串的字符,你几乎可以在没有并行数组的情况下做到这一点。(例如,作为 null 字符。
以下内容留下了从 1 开始的索引(我是 Fortran 程序员!
# include <iostream>
# include <vector>
# include <string>
# include <algorithm>
# include <iterator>
using namespace std;
int main()
{
int m;
string T;
cout << "Enter m: "; cin >> m;
cout << "Enter string: "; cin >> T;
vector<int> arr(m);
cout << "Enter " << m << " positions [1-indexed]: ";
for (auto &x : arr ) cin >> x;
// MARK character in string at given index position (as the null character, say)
for (int i = 0; i < m; i++)
{
T[arr[i]-1] = 0;
copy_if( T.begin(), T.end(), ostream_iterator<char>( cout ), [](char &c){ return c; } );
cout << '\n';
}
}
跑:
Enter m: 4
Enter string: abcd
Enter 4 positions [1-indexed]: 4 1 3 2
abc
bc
b
实际上,我刚刚发现,如果你用 char(7) 标记它,那么你可以只输出字符串而不是使用 copy_if。不过,不知道这是否是标准行为。
for (int i = 0; i < m; i++)
{
T[arr[i]-1] = 7;
cout << T << '\n';
}
评论
arr[i]-1
将从 1 开始的索引转换为从 0 开始的索引。问题就在于你在哪里做这件事。我建议在读取输入时执行一次,而不是每次使用索引时都执行一次
index=position-1
arr
pos
评论
abc
abcd