在C ++中实现查找和替换过程

时间:2014-03-27 18:34:12

标签: c++ algorithm

只是为了好玩,我正在尝试编写像文字处理器一样的查找和替换程序。我想知道是否有人可以帮我弄清楚我做错了什么(我得到了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;
}

3 个答案:

答案 0 :(得分:1)

像大多数编辑一样,发现和替换会涉及到常规 表达式。如果您正在寻找的只是文字 替换,你需要的功能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()是为了避免重新扫描文本 你刚插入,这可能导致无限循环,为 与上述相同的原因。)

答案 1 :(得分:1)

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

可能最有效的方法是:

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

    当第1步返回位置std::string::npos时结束。

答案 2 :(得分:0)

1)你不要将找到的单词的第一个符号推入​​&#34; thisword&#34;变量

2)你只使用空格符号&#39; &#39;作为分隔符,以及逗号&#39;,&#39;。你的程序会找到&#34; dawg,&#34;不是&#34; dawd&#34;

以下代码有效,但您应该考虑其他单词分隔符。你真的需要只替换整个单词,或只是替换符号序列吗?

#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;
}