c++vector

Using vectors to bleep some predefined strings


So i'm currently doing the exercices in my programming book "Programming: Principles and practice using c++" from Bjarne Stroustrup and i'm curently stuck at one exercice. Basically, the exercice is to write a program that bleeps out words it doesn't like. The way it works is that the user inputs a string and the program repeats the word. If the word the user enters is part of the dislike vector, the word is replaced by "Bleep". (I don't know if I explained this right, but it shouldn't be to complicated to understand).

This is my version of the program:

int main()
{
    string dislike = "Potato";
    string words = " ";

    cout << "Please enter some words: " << endl;
    while(cin>>words)
    {
        if(words==dislike)
        {
            cout << "Bleep!" << endl;
        }

        else
        {
            cout << words << endl;
        }
    }
    system("pause");
    return 0;
}

As you can see, this version isn't using vectors (and it should, because the exercice is right after the explanation of vectors in the chapter). So my question is, how can I implement a vector with many "dislike" words in it like this:

vector<string>dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");

and make it so it works like my other version without vectors (repeats words, but bleeps the dislike words). I can't seem to understand how to navigate in a vector so that it only bleeps the "dislike" words.

If someone could give me a hand and explain to me how it works (please do not just give me the answer) it would be very appreciated.

Thank you for your time and help, learning c++ alone isn't always simple, and I thank this website for making my learning curve a bit easier.

bobicool


Solution

  • Ok, let me explain a simple approach to it. There are more elegant ones, but for now it's important that you get a feeling of how std::vector can be accessed and how to compose control structures correctly.

    Step 1 - looping through all elements of a vector

    You can use iterators to go through all elements of a vector.

    for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {
    
       // now *it gives access to the current element (here: current dislike word)
       if (*it == words) {
           // ... yeah, we found out the current word is on the list!
       }         
    }
    

    You get an iterator to the first element in a vector by calling begin(), then keep incrementing (++it) it until you reached the end of the vector. I use const_iterator here because I'm not going to modify any elements, if you need to, use iterator.

    with a std::vector, indexing via [index] is also possible (but not recommended, usually):

    for(size_t i = 0;i < dislike.size(); ++i) {
       // dislike[i] is the current element
    
       if (dislike[i] == words) {
          // huuuuray! another BEEEP candidate
       }
    }
    

    Step 2 - break the loop early

    As soon as you know what for sure that we have a dislike word, you don't need to search the vector further.

    for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {   
      if (*it == words) {
         // we found a positive match, so beep and get out of here
         cout << "Bleep!" << endl;
         break;
      }         
    }
    

    Step 3 - make a note if we handled a word already

    bool is_beep = false;
    for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {   
      if (*it == words) {
         // we found a positive match, so beep and get out of here
         cout << "Bleep!" << endl;
         is_beep = true;
         break;
      }         
    }
    // this is not a dislike word if is_beep is false, so print it as usual
    if (!is_beep) {
       cout << words << endl;
    }
    

    Step 4 - putting it all together

    int main()
    {
        vector<string>dislike;
        dislike.push_back("Potatoes");
        dislike.push_back("Peanuts");
        dislike.push_back("Coconut");
        string words = " ";
    
        cout << "Please enter some words: " << endl;
        while(cin>>words)
        {
            bool is_beep = false;
            for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {   
               if (*it == words) {
                // we found a positive match, so beep and get out of here
                cout << "Bleep!" << endl;
                is_beep = true;
                break;
              }         
            }
           // this is not a dislike word if is_beep is false, so print it as usual
           if (!is_beep) {
                cout << words << endl;
           }
        }
        system("pause");
        return 0;
    }
    

    Check out std::find for a more idiomatic solution - it basically saves you the inner loop. You can also get rid of that bool in the last code sample if you re-structure a bit. I'll leave that as an exercise to you (hint: keep the iterator alive and check out its value after terminating the loop).