我知道这是一个经常被问到的问题并且如果它是愚蠢的而道歉,但我正在尝试从文件中的字符串中删除重复的字符并将新字符串放入另一个文件中。那部分情况正常。
我遇到的主要问题是使用我的算法去除字符,它只适用于相同的连续字符,甚至只是部分字符。我试图在for循环中使用.erase()
来执行此操作,但正如我所说它不起作用。我哪里错了?
string removeRepeats(string strIn,string &strOut){
int i;
int len = strIn.length();
for(i = 0;i < len; i++){
if(strIn[i] == strIn[i+1]){
strIn.erase(i+1,1);
}
len = strIn.length();
}
return strOut = strIn;
}
这些是来自示例文件的输入字符串的字符串:
aaaaaabbccccc
nnnnmmmvvv
rocko
refrigerate pool
fungus
这是他们在程序运行后出现的结果:
aaabccc
nnmmvv
rocko
refrigerate
pol
fungus
答案 0 :(得分:2)
您只检查相邻字符:if(strIn[i] == strIn[i+1]) { ...
你可以更有效地做到这一点,但我想先做一些评论:
strOut
和传递strOut
。你应该选择其中一个。在我下面写的代码中,我选择返回strOut
。 for
- 循环中初始化变量。除了循环变量之外,您还希望尝试最小化其他变量的范围。在代码中,您可以创建变量len
。如果您使用了for(size_t i = 0; i < strIn.length(); ++i)
,则无需在if
- 语句后更新它。return strOut = strIn;
很奇怪。你不会经常在C ++中看到这一点(参见返回或通过引用传递,但不能同时传递)。如果您真的想要return strOut
,那么在更改strIn
并在副本上执行所有字符串突变之前创建std::string removeRepeats(std::string strIn){
std::string strOut = strIn;
for(size_t i = 0;i < strOut.length(); ++i){
if(strOut[i] == strOut[i+1]){
strOut.erase(i+1,1);
}
}
return strOut;
}
的副本会更有意义。以下是我对您的代码所做的更改(无论算法的正确性如何):
std::string remove_repeats(std::string input_string) {
// You have seen no characters yet
bool seen[128] = { false };
std::string output_string = "";
// for every character in the string
for(auto c: input_string) {
// if we haven't seen the the ASCII yet
if(!seen[128-c]) {
// append it to our output string
output_string+=c;
// mark the letter as seen
seen[128-c] = true;
}
}
return output_string;
}
这会更清洁,你会发现。
由于只有128个ASCII字符,您可以创建一个布尔数组并检查您之前是否看过某个字符。
因为你想保留重复字符的最后,我们需要有点棘手。下面的代码将保留重复字符的第一个。
std::string remove_repeats(std::string input_string) {
// You have seen no characters yet
bool seen[128] = { false };
std::string output_string = "";
// for every character in the string
for(size_t i = 0; i < input_string.length(); ++i) {
char c = input_string[i];
// if we haven't seen the the ASCII yet
if(!seen[128-c]) {
// append it to our output string
output_string+=c;
// mark the letter as seen
seen[128-c] = true;
}
}
return output_string;
}
这是ideone。
如果你不能使用C ++ 11,你可以这样做:
std::string remove_repeats(std::string input_string) {
// You have seen no characters yet
bool seen[128] = { false };
// Reverse the input string
std::reverse(input_string.begin(), input_string.end());
std::string output_string = "";
// for every character in the string
for(auto c: input_string) {
// if we haven't seen the the ASCII yet
if(!seen[128-c]) {
// append it to our output string
output_string+=c;
// mark the letter as seen
seen[128-c] = true;
}
}
// Reverse the output string
std::reverse(output_string.begin(), output_string.end());
return output_string;
}
这是非C ++ 11版本的ideone。
你想保留最后一个。这是它变得有趣的地方。
如果我们反转字符串(1),运行我们的算法(2),然后重新反转(3),我们将获得所需的输出:
(1)“你好世界” - &gt; “dlrow olleh”
(2)“dlrow olleh” - &gt; “dlrow eh”
(3)“dlrow eh” - &gt; “他的世界”
以下是如何执行此操作:
#include <algorithm>
std::reverse
确保dispatch_async(dispatch_get_main_queue()) { () -> Void in
if let object = currentObject.objectForKey("postText") as? String {
postTextView.text = "the text field has some text added"
}
}
。
最终工作ideone
答案 1 :(得分:1)
所以你需要做的是在寻找重复字符时你是一个嵌套for循环你现有的for循环所以:
string removeRepeats(string strIn,string &strOut){
int i;
int k;
int len = strIn.length();
for(i = 0;i < len; i++){
for(k = i+1 ; k < len; k++){
if(strIn[i] == strIn[k]){
strIn.erase(k,1);
k--;
}
}
len = strIn.length();
}
return strOut = strIn;
}
这将修复程序的比较部分。你的问题在于你的代码只检查了每个数字,而不是所有其他字符