在c++中实现一个查找和替换过程



只是为了好玩,我正在尝试编写一个像文字处理器那样的查找和替换过程。我想知道是否有人可以帮助我找出我做错了什么(我得到一个Timeout错误),并可以帮助我写一个更优雅的过程。

#include <iostream>
#include <string>
void find_and_replace(std::string& text, const std::string& fword, const std::string& rword)
{
     for (std::string::iterator it(text.begin()), offend(text.end()); it != offend;)
     {
        if (*it != ' ')
        {
           std::string::iterator wordstart(it);
           std::string thisword;
           while (*(it+1) != ' ' && (it+1) != offend)
                thisword.push_back(*++it);   
           if (thisword == fword)
               text.replace(wordstart, it, rword);
        }
        else {
            ++it;
        }
     }   
}
int main()
{
    std::string S("Yo, dawg, I heard you like ...");
    std::string f("dawg");
    std::string w("dog");
    // Replace every instance of the word "dawg" with "dog":
    find_and_replace(S, f, w);
    std::cout << S;
    return 0;
}

像大多数编辑器一样,查找和替换将涉及常规的表达式。如果你想要的只是字面意思替换,你需要的函数是std::search,来找到文本要替换,而std::string::replace,要做实际的替换。你将面临的唯一问题是:std::string::replace可以使你的迭代器失效。你可以总是从字符串的开头开始搜索,但是这个可能导致无休止的循环,如果替换文本包含搜索字符串(如s/vector/std::vector/)。您应该转换从std::search返回的迭代器在执行替换(offset = iter - str.begin())之前,将其偏移量转换为字符串,然后将其转换回迭代器( iter = str.begin() + offset + replacement.size())。(添加replacement.size()是为了避免重新扫描文本你刚刚插入,这可能会导致无限循环,对于

  • 使用text.replace可能会使任何进入文本的迭代器失效(即itoffend):这是不安全的
  • 将每个字符复制到一个临时字符串(每次开始一个新单词时创建和销毁)是浪费的

最简单的方法是:

  1. 使用find找到第一个匹配的子字符串:它返回一个position,当你替换子字符串时不会无效
  2. 检查是否:
    1. 子字符串位于文本的开头,或者前面有分隔符
    2. 子字符串位于文本的末尾,或者后面有一个分隔符
  3. 如果2.1和2.2为真,替换子字符串
  4. 如果你替换了它,增加position(从1)由你的替换字符串的长度
  5. 否则将position增加您搜索的字符串的长度
  6. 从1开始重复,这次从position(从4/5)开始查找
当第一步返回位置std::string::npos

结束

1)你不把找到的单词的第一个符号推入"thisword"变量

2)您只使用空格符号' '作为分隔符,那么逗号','呢?你的程序会找到单词"dawg ",而不是"dawd"

下面的代码可以工作,但是您应该考虑其他单词分隔符。你真的只需要替换整个单词,还是仅仅替换符号序列?

#include <iostream>
#include <string>
void find_and_replace(std::string& text, const std::string& fword, const std::string& rword)
{
     for (std::string::iterator it(text.begin()), offend(text.end()); it != offend;)
     {
        if (*it != ' ' && *it != ',')
        {
           std::string::iterator wordstart(it);
           std::string thisword;
           while ((it) != offend && *(it) != ' ' && *(it) != ',')
                thisword.push_back(*it++);   
           if (thisword == fword)
               text.replace(wordstart, it, rword);
        }
        else {
            ++it;
        }
     }   
}
int main()
{
    std::string S("Yo, dawg, I heard you like ...");
    std::string f("dawg");
    std::string w("dog");
    // Replace every instance of the word "dawg" with "dog":
    find_and_replace(S, f, w);
    std::cout << S;
    return 0;
}

最新更新