0

I'm trying to replace multiple words with their "pirate pair", for example:

Normal: "Hello sir, where is the hotel?"

Pirate: "Ahoy matey, whar be th' fleagbag inn?"

This is what I tried before:

#include<iostream>
#include<string>
#include<conio.h>

using namespace std;

void speakPirate(string s);

int main()
{
    string phrase;

    cout << "Enter the phrase to Pirate-Ize: ";
    getline(cin, phrase);

    speakPirate(phrase);

    _getch();
    return 0;
}

void speakPirate(string s)
{
    int found;

    // list of pirate words
    string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };

    // list of normal words
    string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };

    for (int i = 0; i < s.length(); i++)
    {
        found = s.find(normal[i]);

        if (found > -1)
        {
            string left = s.substr(0, found - 1);   // get left of the string
            string right = s.substr(found + pirate[i].length(), s.length());  // get right of string
            s = left + " " + pirate[i] + " " + right;   // add pirate word in place of normal word
        }
    }

    cout << s;
}

But it didn't really work and was very buggy, so I tried using the replace() function instead:

#include<iostream>
#include<string>
#include<conio.h>

using namespace std;

void speakPirate(string s);

int main()
{
    string phrase;

    cout << "Enter the phrase to Pirate-Ize: ";
    getline(cin, phrase);

    speakPirate(phrase);

    _getch();
    return 0;
}

void speakPirate(string s)
{
    int found;

    // list of pirate words
    string pirate[12] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer", "galley", "fleabag inn" };

    // list of normal words
    string normal[12] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your", "restaurant", "hotel" };

    for (int i = 0; i < s.length(); i++)
    {
        found = s.find(normal[i]);

        if (found > -1)
        {
            s.replace(found, found + pirate[i].length(), pirate[i]);
        }
    }

    cout << s;
}

I'm not sure why, but this doesn't really work either. I also notice that when I try changing a larger word into a smaller word, some of the original word is leftover, for example:

    Enter the phrase to Pirate-Ize: hello
    ahoyo

And I just noticed that it sometimes might not even change the word at all, for example:

    Enter the phrase to Pirate-Ize: where
    where

How come? Could someone please tell me what I need to do or a more effective solution that I could implement? Thanks a lot.

Paulo Freitas
  • 13,194
  • 14
  • 74
  • 96
Kawaiiii
  • 157
  • 1
  • 8

2 Answers2

2

Here you iterate over the length of the text:

for (int i = 0; i < s.length(); i++)

It should be the length of the array of texts, something like

for (int i = 0; i < 12; i++)

However, you should use a std::map to model the mapping between the normal words and their pirate version.

std::map<std::string, std::string> words = {
  {"hello", "ahoy"},
  // .. and so on
};

for(auto const & kvp : words) 
{
   // replace kvp.first with kvp.second
}
Marius Bancila
  • 16,053
  • 9
  • 49
  • 91
  • Thanks for notifying me that I was using the wrong condition for my for loop, but I have never heard of std::map before, are there any other solutions? – Kawaiiii Feb 24 '15 at 21:48
1

Marius is correct that the major error is that you need to iterate over the length of the arrays. A different way than mapping would be to use erase() and insert() where you used replace(). replace() does not account for the lengths of the strings being different, but removing a substring and then adding in a new substring will. This can be done as follows

for (int i = 0; i < 12; i++)
{
    found = s.find(normal[i]);

    // Locate the substring to replace
    int pos = s.find( normal[i], found );
    if( pos == string::npos ) break;
    // Replace by erasing and inserting
    s.erase( pos, normal[i].length() );
    s.insert( pos, pirate[i] );
}
David
  • 757
  • 1
  • 7
  • 17
  • Thanks a lot for that simple solution! but are there other ways to fulfill this task without using the erase() or insert() function? I ask this since I'm kind of new, and I'd like to see the actual logic behind this. Thanks. – Kawaiiii Feb 24 '15 at 21:49
  • The easiest thing that comes to mind would be to write the erase and insert functions yourself. They are only a few lines each and are great practice. For erase, use find to find the index of the string. Then concatenate the substring of the original string up to that index with another substring that will be from the index + lengthOfStringSearchedFor to the end of the original string. For insert, concatenate the substring up to the index with the word you want to add and then with the remaining part of the string after the index. – David Feb 24 '15 at 21:54