为什么替换字符串会替换另一个字符串的一部分?

时间:2018-10-24 13:57:10

标签: c++ fstream

我今天写了一小段代码,关于替换文本文件中的单词。 尽管它替换了给定的单词,但它也删除了其他字符串的一些空格和某些部分。 我希望它仅在保持原样的同时替换给定的单词。 我不知道该怎么办。任何帮助将不胜感激!

文件原始数据:

Is anyone there?  
Who survived?  
Somebody new?  
Anyone else but you  
On a lonely night  
Was a burning light  
A hundred years, we'll be born again  

用“搬运工”代替“任何人”时的输出:

Is anyonportere?  
Who survived?  
Somebody new?  
anporterlse but you  
On a lonely night  
Was a burning light  
A hundred years, we'll be born again  

代码:

    #include<iostream>
    #include<fstream>
    #include<cstdlib>
    #include<cstring>
    using namespace std;

    int main(int argc , char* argv[])
    {
        string old_word,new_word;
        int no=0;
        old_word=argv[1];
        new_word=argv[2];

        if(argc<4)
        {
            cout<<"\nSome Arguments are missing";
            return 0;
        }   

        if(strlen(argv[1])!=strlen(argv[2]))
        {
            cout<<"\nReplacement is not possible as size of New wor dis not equal to old word";
return 0;
        }

        fstream obj;
        obj.open(argv[3],ios::in|ios::out);
        if(!obj)
        {
            cout<<"\nError in file creating";
            return 0;
        }   
        string fetch_word;
        while(1)
        {
            if(obj.eof())
            {
                break;
            }
            else
            {
                int pos=obj.tellg();
                obj>>fetch_word;
                if(fetch_word==old_word)
                {
                    no++;
                    obj.seekp(pos);
                    obj<<new_word;
                }
            }
        }
        if(no==0)
        {
            cout<<"\nNo Replacement Done . Zero Replacement Found";
        }
        else
        {
            cout<<"\nReplacement Done . Replacement Found ="<<no<<endl;
        }
        obj.close();
        return 0;
    }   

2 个答案:

答案 0 :(得分:1)

如果我们使用字符串“有人在吗?”

在读取单词“ Is”之后,读取头位于“ Is”之后的空格上,因此tellg将返回2。 现在,您正在阅读下一个单词,跳过空白,开始阅读,直到下一个空格字符,您正在阅读“任何人”单词并将其替换词放在位置(2)。

所以它应该给你字符串:“在那附近有东西吗?”

不是您要提出的目标,而是您获得的结果。

要解决此问题,您应该在读取位置之前忽略空格:

像这样:

//#include <cwctype> for iswspace

//eat white spaces
while(iswspace(obj.peek()))
     obj.ignore();
//now read head is on the beginning of a word, you can take position.
int pos=obj.tellg();        

编辑

您必须进行调试,看看tellg在第一行中是否返回3,然后再阅读“ anyone”一词。我建议为每一次替换都添加一些调试打印。

like:

 if(fetch_word==old_word)
 {
    no++;
    cout<<"Replacing in pos "<< pos <<endl;
    obj.seekp(pos);
    obj<<new_word;
 }

现在您可以检查:

  • pos是否正确? (您可以尝试搜索并再次阅读该单词)
  • seekp是否成功? (您可以使用tellp进行检查!)
  • obj.seekp(3); obj<<"porter";会在正确的位置替换字符串吗?

答案 1 :(得分:0)

#include <cctype>
#include <cstdlib>
#include <string>
#include <fstream>
#include <iostream>

int main()
{
    std::string old_word{ "anyone" };
    std::string new_word{ "porter" };

    if (old_word.length() != new_word.length()) {
        std::cerr << "Sorry, I can only replace words of equal length :(\n\n";
        return EXIT_FAILURE;
    }

    char const *filename{ "test.txt" };
    std::fstream obj{ "test.txt", std::ios::in | std::ios::out };
    if (!obj.is_open()) {
        std::cerr << "Couldn't open \"" << filename << "\" for reading and writing.\n\n";
        return EXIT_FAILURE;
    }

    std::string word;
    for (std::streampos pos; pos = obj.tellg(), obj >> word;) {
        if (word == old_word) {
            obj.seekg(pos);  // set the "get" position to where it were before extracting word
            while (std::isspace(obj.peek()))  // for every whitespace we peek at
                obj.get();                    // discard it
            obj.seekp(obj.tellg());  // set the "put" position to the current "get" position
            obj << new_word;  // overwirte word with new_word
            obj.seekg(obj.tellp());  // set the "get" position to the current "put" position                                             
        }
    }
}