【问题标题】:Need help erasing and inserting in C++需要帮助在 C++ 中擦除和插入
【发布时间】:2013-09-23 20:23:38
【问题描述】:

所以基本上我想创建一个接受字符串的格式函数,并用用户想要替换的任何内容替换该字符串中的单词。起初我对不可延迟的迭代器有一些问题,直到我意识到当你改变一个字符串的大小时,你可以使任何迭代器无效。它现在不再抛出异常,现在输出与输入相同。有什么建议???

string& formatFn(string& s, string& oldWord, string& newWord)
{
    string word = "";
    for (auto iter1 = s.begin(); iter1 != s.end(); ++iter1)
    {       
            string tmpWord = "";                         
        if (!isblank(*iter1))       // Testing for whitespace
        {
            tmpWord += *iter1;
            if (tmpWord == oldWord)
            {
                string::iterator beg = iter1 - word.size();
                string::iterator end = iter1;
                auto sIter = s.erase(beg, end);                 // Get the position returned by erase
                auto i = sIter - s.begin();                     // Get an index 
                s = s.insert(s[i], newWord);
            }
        }
        if (isblank(*iter1))
        {
            tmpWord.clear();
        }
    }
    return s;
}

【问题讨论】:

  • 你为什么不使用string::findstring::replace呢?

标签: c++ insert erase


【解决方案1】:

如果您已经使用字符串,为什么不使用所有方法?

for (auto it = text.find(o_text); it != string::npos; it = text.find(o_text)){
    text.replace(it, o_text.size(), n_text);
}

【讨论】:

  • 看来 OP 想要替换 words,find 会找到任何子字符串,而不仅仅是整个单词。
【解决方案2】:
string::iterator beg = iter1 - word.size();

我不确定word 究竟做了什么。您正在尝试删除oldWord,对吗?那么应该是:

string::iterator beg = iter1 - oldWord.size();

编辑:这是您的代码的改进版本:

string formatFn(const string& s, const string& oldWord, const string& newWord) {
    string result = "";     // holds the string we want to return
    string word = "";       // while iterating over 's', holds the current word

    for (auto iter1 = s.begin(); iter1 != s.end(); ++iter1)  {       
        if (!isblank(*iter1))
            word += *iter1;
        else {    // if it is a whitespace, it must be the end of some word
            // if 'word' is not same as 'oldword', just append it
            // otherwise append 'newWord' instead

            if (word == oldWord)
                result += newWord;
            else
                result += word;
            result += *iter1;
            word.clear();    // reset 'word' to hold the next word in s
        }
    }

    // the end of the string might not end with a whitespace, so the last word
    // might be skipped if you don't make this test

    if (word == oldWord)
        result += newWord;
    else
        result += word;

    return result;
}

【讨论】:

    【解决方案3】:

    你太复杂了:

    std::string replace_all(std::string s, const std::string& sOld, const std::string& sNew)
    {
        std::size_t p = s.find(sOld);
        while (p != std::string::npos)
        {
            s.replace(p, sOld.length(), sNew);
            p = s.find(sOld, p + sNew.length());
        }
        return s;
    }
    

    如果您只想替换整个单词(您当前的尝试不会这样做):

    #include <iostream>
    #include <string>
    
    bool test(const std::string& s, const std::string& sOld, std::size_t pos)
    {
        return (pos == 0 || !::isalpha(s[pos - 1])) && (!::isalpha(s[pos + sOld.length()]) || pos + sOld.length() >= s.length());
    }
    
    std::size_t find_word(const std::string& s, const std::string& sOld, std::size_t pos)
    {
        pos = s.find(sOld, pos);
        while (pos != std::string::npos && (!test(s, sOld, pos) && pos < s.length()))
        {
            pos++;
            pos = s.find(sOld, pos);
        }
        return pos;
    }
    
    std::string replace_all(std::string s, const std::string& sOld, const std::string& sNew)
    {
        std::size_t p = find_word(s, sOld, 0);
        while (p != std::string::npos && p < s.length()) 
        {
            s.replace(p, sOld.length(), sNew);
            p = find_word(s, sOld, p + sNew.length()); 
        }
        return s;
    }
    
    int main() 
    {
        std::string sOrig = "eat Heat eat beat sweat cheat eat";
        std::string sOld = "eat";
        std::string sNew = "ate";
        std::string sResult = replace_all(sOrig, sOld, sNew);
        std::cout << "Result:  " << sResult << std::endl;
        // Output:  "ate Heat ate beat sweat cheat ate"
        return 0;
    }
    

    【讨论】:

    • 我认为 OP 要求是替换 words,而不是任何子字符串。这就是为什么他有所有的空白处理。
    • 为什么不接受对字符串的引用并改变它呢?然后您可以返回替换的单词数,例如std::size_t replace_all(std::string&amp; s, const std::string&amp; old, const std::string&amp; new);
    • @rwols:你可以这样做,但这会改变原来的。这种方式需要一个临时的并返回它(相当于通过 const-reference 传递并制作一个副本),保持原件完好无损。如果可以接受原始修改,则返回void 并通过引用传递也可以。重点是算法。
    • @john:如果您只将单词作为sOld 传递,那么所有被替换的都是匹配的单词(无需担心空格)。
    • 另外,如果他想在sOld参数中传入多个单词并将它们全部替换为sNew中的内容,更改@987654328的参数类型是一件相当简单的事情@ 到 const std::vector&lt;std::string&gt;&amp; 修改算法以循环所有 sOld 以进行替换。
    猜你喜欢
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    • 1970-01-01
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多