0

beginner here, Im getting this error within my program which is supposed to find a word in a string then, replace that word with any that you input. When I input multiple words into the str1, it says this:

terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::erase:__pos (which is 18446744074709551615) > this->size() (which is 9)

Heres my code:

#include <iostream>
#include <string>

using namespace std;

void findReplace(string& str1,string& str2,string& str3);

int main() 
{
string str1, str2, str3;

cout << "Enter a sentence that you would like to analyze: \n";
cin >> str1;
cin.ignore();
cout << "Enter a word that you would like to search for: \n";
cin >> str2;
cin.ignore();
cout << "Enter a word that would replace the word that was found: \n";
cin >> str3;
cin.ignore();

findReplace(str1,str2,str3);

return 0;
}

void findReplace(string& str1,string& str2,string& str3)
{
  int length= 0;
  int str2len= 0;
  int str3Length = 0;

  length = str1.length();
  str2len = str2.length();
  str3Length = str3.length();
  
  int found = str1.find(str2);

  if ((found!= string::npos))
  {
    cout << str2 << " found at " << found << endl;
  }

  str1.erase(found, str2len);

  str1.replace(found, str3Length, str3 );
  
  cout << str1;

}
Piklez
  • 13
  • 4
  • `18446744074709551615` looks a lot like you tried to erase a position that wasn't found (aka `npos`) – user4581301 Sep 18 '20 at 00:48
  • 1
    What is the input that produces the crash? – Retired Ninja Sep 18 '20 at 00:50
  • The `if ((found!= string::npos))` pints out if the item was found, but it doesn't prevent the erase and replace of unfound items. Move those two instructions into the body of the `if`. – user4581301 Sep 18 '20 at 00:50
  • I moved the erase function and replace function into the if statement, but now when i input more that 2 words into str1, it skips the cin for str2 and str3. – Piklez Sep 18 '20 at 00:57
  • `cin >> str1;` can only read one word. You need [`std::getline`](https://en.cppreference.com/w/cpp/string/basic_string/getline) most likely. – user4581301 Sep 18 '20 at 01:02
  • Your debugger will show you where this exception is thrown, and the reason why. Have you already tried to debug your program, in your debugger? What did you see? And if you haven't tried using your debugger yet, why not? – Sam Varshavchik Sep 18 '20 at 01:03
  • I used the getline function for str1 and that seemed to fix the problem, thanks guys. And my debugger had no exceptions thrown otherwise i wouldve stated that. – Piklez Sep 18 '20 at 01:05
  • Better than telling us what input produces the crash would be replacing the lines like `cin >> str1;` with lines like `str1 = "This string causes the crash.";`. See also [mre] (MRE), as constructing a MRE is a valuable debugging tool. – JaMiT Sep 18 '20 at 01:06
  • Sam's right. The debugger would have halted and almost pointed you right at the call to `erase` (you would have had to track back up the call stack a bit), so either you did not test this case while debugging or you didn't actually use [the debugger.](https://en.wikipedia.org/wiki/Debugger) – user4581301 Sep 18 '20 at 01:17

1 Answers1

0

The error message contains two big hints: basic_string::erase, the exception was thrown in the call to erase and 18446744074709551615 is maximum 64 bit unsigned in int which on a modern 64 bit system matches the definition of npos

static const size_type npos = -1;

So let's take a look at what lead up to the call to erase:

  int found = str1.find(str2); // find str2

  if ((found!= string::npos))
  { // found str2
    cout << str2 << " found at " << found << endl; // print that we found it
  }

  str1.erase(found, str2len); // erase it (even if we didn't find it)

  str1.replace(found, str3Length, str3 ); // replace it (even if we didn't find it)

Fix:

  auto found = str1.find(str2); // Note: Position ISN'T an int. auto will 
                                // find and use correct type. If auto's not available
                                // size_t will do the job.

  if ((found!= string::npos))
  { // found str2
    cout << str2 << " found at " << found << endl; // print that we found it
    str1.erase(found, str2len); // erase it 

    str1.replace(found, str3Length, str3 ); // replace it 
  }

In addition:

cin >> str1;

will read only one word. Since you need a sentence, use std::getline

You can discard all of the cin.ignore()s. They are useless here. >> will consume any leftover whitespace before the token tit finds. It will leave whitespace after the token, so watch out for Why does std::getline() skip input after a formatted extraction? if you place a std::getline after a >>.

user4581301
  • 29,019
  • 5
  • 26
  • 45