前言,我最近开始自学编程,因此他就像新手一样。如果您在我的代码中发现任何不良的一般编码习惯(包括与我的问题无关),请告诉我,因为我真的可能不知道更好。
问题:
我正在尝试制作一小段代码,用新字符串替换目标字符串的出现。我知道存在可以大大改进过程(即查找,替换等)的函数,为了练习的目的,我正在避免这些并限制自己使用迭代器,插入和擦除。我也知道还有许多其他地方可以改进代码,我也喜欢这些部分的输入,但我主要关注的是我发现的异常行为。我现在拥有的是:
#include <iostream>
#include <string>
bool scan(const std::string, const std::string::iterator);
//replaces occurrences of oldVal in s with newVal
std::string& replace (std::string &s, const std::string &oldVal, const std::string &newVal)
{
std::string::iterator iter = s.begin();
while (iter != s.end()) { //process s
if (scan(oldVal, iter)) { //Checks if characters match
iter = s.erase(iter, iter + oldVal.size()); //deletes occurrence of oldVal
iter = s.insert(iter, newVal.begin(), newVal.end()); //inserts newVal in oldVal's place
iter = iter + newVal.size(); //continues processing after inserted newVal
}
else
++iter; //Move to next character in s to process
}
return s;
}
//This function returns 1 if the strings match and 0 if they do not
bool scan(const std::string target, std::string::iterator iter)
{
for (auto beg = target.begin(); beg != target.end(); ++beg) {
std::cout << "Line 27 " << *iter << " " << *beg << std::endl; //MAIN CONCERN! This line is run twice.
//(It was solely added for debugging. Verifies values being compared)
if (*iter != *beg) {
std::cout << "Condition met; "
<< *iter << " != " << *beg << std::endl; //added for debugging. Double verifies values post-comparison
return 0;
}
++iter;
++beg;
}
return 1;
}
int main()
{
std::string mainStr, oldStr, newStr;
std::getline(std::cin, mainStr); //Overall it'd be better for s to be a list of strings, but my concern is with line 27
std::cin.clear();
std::cin >> oldStr >> newStr;
std::cout << "Output: " << replace(mainStr, oldStr, newStr) << std::endl; //Prints post-replacement string
}
似乎正在发生的是第27行(std :: cout&lt;&lt;“Line 27”......)在第一次扫描时被执行两次。例如,给定输入:
tho
tho though
我得到输出(//是我在运行之外添加的评论,即仅用于此帖子)
Line 27 t t //This part is run twice and does weird things
Line 27 h o //If it was just incrementing it should read "Line 27 h h"
Condition met; h != o //This shouldn't happen; The condition should have tested t != t
Line 27 h t //It's seems fine from this point onwards
Condition failed; h != t
Line 27 o t
Condition failed; o != t
Output: tho
这可能是什么原因?
谢谢!
答案 0 :(得分:1)
我发现一个错误:在scan()
beg
迭代器在每次迭代中增加两次,原因是++beg
循环线for(...)
和beg++
在循环结束时。
答案 1 :(得分:0)
提供的代码存在一些问题。主要问题在'scan(...)',你在每次循环中都会增加'beg'迭代器两次,一次在for()构造中:
for (auto beg = target.begin(); beg != target.end(); ++beg)
并且在for循环结束时一次:
++iter;
++beg;
scan(...)函数中的几个小点是将'target'作为引用传递(const std :: string&amp; target),并返回false / true,而不是0/1。
我在Ubuntu 12.04上使用g ++ - 4.8进行了检查,这似乎使用了c ++ 98定义的insert,它没有返回一个interator(即函数是“void insert(iterator p,InputIterator first, InputIterator last);“)....这里是稍微修改的代码来解决这个问题:
#include <iostream>
#include <string>
bool scan(const std::string&, const std::string::iterator);
//replaces occurrences of oldVal in s with newVal
std::string& replace (std::string &s, const std::string &oldVal, const std::string &newVal)
{
std::string::iterator iter = s.begin();
while (iter != s.end()) { //process s
if (scan(oldVal, iter)) { //Checks if characters match
iter = s.erase(iter, iter + oldVal.size()); //deletes occurrence of oldVal
// Doesn't work on g++4.8 on Ubuntu, still seems to use the c++98 "void insert (iterator p, InputIterator first, InputIterator last);"
//iter = s.insert(iter, newVal.begin(), newVal.end()); //inserts newVal in oldVal's place
// If the iter == s.end(), then pos will not be the value we need.
size_t pos = iter == s.end()? s.size() : std::distance(s.begin(), iter);
s.insert(iter, newVal.begin(), newVal.end()); //inserts newVal in oldVal's place
iter = s.begin() + pos;
iter = iter + newVal.size(); //continues processing after inserted newVal
}
else
++iter; //Move to next character in s to process
}
return s;
}
//This function returns 1 if the strings match and 0 if they do not
bool scan(const std::string& target, std::string::iterator iter)
{
for (auto beg = target.begin(); beg != target.end(); ++beg) {
std::cout << "Line 27 " << *iter << " " << *beg << std::endl; //MAIN CONCERN! This line is run twice.
//(It was solely added for debugging. Verifies values being compared)
if (*iter != *beg) {
std::cout << "Condition met; "
<< *iter << " != " << *beg << std::endl; //added for debugging. Double verifies values post-comparison
return false;
}
++iter;
}
return true;
}
int main()
{
std::string mainStr, oldStr, newStr;
std::getline(std::cin, mainStr); //Overall it'd be better for s to be a list of strings, but my concern is with line 27
std::cin.clear();
std::cin >> oldStr >> newStr;
std::cout << "Output: " << replace(mainStr, oldStr, newStr) << std::endl; //Prints post-replacement string
}