6
\$\begingroup\$

Problem:

Censor Unwanted words.

Solution:

Note: I am beginner and self learning programming by reading the book "Programming: Principles and Practises" by Bjarne Stroustrup and this a "try this" exercise from chapter 4.

#include <iostream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::string> words;

    std::cout << "Enter a list of words.\n";
    std::string temp;

    while(std::cin>>temp){
        words.push_back(temp);
        }

    for(auto w : words){
        if(w=="idiot"||w=="nonsense"||w=="hyper"){
            std::cout<<"BlEEP"<<" ";
        }
        else std::cout<<w<<" ";
    }
}

Sample Test run.

Sample output of a test run

\$\endgroup\$
10
\$\begingroup\$

That's fine. You have exactly the includes you need, you didn't use using namespace, and you've used std::cin correctly.

However, I'd recommend you to use a code formatter next time, since some for your closing braces are misaligned. And if you use braces around a single statement in if, do the same for else.

Other than that, you can take a const auto & word instead of auto w to remove copies. Also word is a nicer name than w. Try to be more verbose, it helps when you read the code a second time.

Since we do not use temp after the while, should keep its scope smaller. We can use a for loop, wrap braces around the while and temp's declaration (which does the same), or write a small (inline) function.

We end up with

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> words;

    std::cout << "Enter a list of words.\n";

    for(std::string temp; std::cin >> temp;){
        words.push_back(temp);
    }

    for(const auto &word : words){
        if(word == "idiot" || word == "nonsense" || word == "hyper"){
            std::cout << "BlEEP" <<" ";
        } else {
            std::cout << word << " ";
        }
    }
}

I've added some whitespace to make the code slightly easier to read. However, our code works well for three words, but what about four, five or even ten? As soon as we have more words than fit in a single line, we probably want to store them in a container.

Exercise

Read the banned words from a file. Use those words to filter the text just like you did.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the valuable review. Could you please give suggestion about the container I should use for this purpose. \$\endgroup\$ – Muhammad Kamal Nov 22 '17 at 2:20
  • 1
    \$\begingroup\$ @MuhammadKamal you can use exclusion. You do not know how many words will be in the text file, so both std::array<std::string> and std::string[] are off. Now we're left with std::vector, std::deque and std::list. Since we only need to add elements at the end, std::vector fits and is usually the best case. However, std::set is also suitable, since it provides \$\mathcal O(log n)\$ search. Therefore: either std::set (better asymptotical complexity) or std::vector (more likely to have better real world performance) or std::vector + std::sort (probably fastest). \$\endgroup\$ – Zeta Nov 22 '17 at 6:59
1
\$\begingroup\$

You can use a ternary here.

std::cout << ( ( w == "idiot" || w == "nonsense" || w == "hyper" ) ? "BlEEP" : w ) << " ";

It's arguable whether it's more readable in this case, but it's still handy to remember you can.

Also, FWIW, if you'd have got more std::cout's, you could've e.g. had using std::cout; - is a matter of personal choice, but if you're really using one of the imports often, you can remove noise this way.

Note that, IMVHO, having a variable called w quite OK if you're using it in tight scope (small methods/functions, lambdas, small loop variables etc.), where its function is obvious (as is in this particular case). Don't do that for variables with larger scopes, though!

\$\endgroup\$
1
\$\begingroup\$

If you store the bad words separately, it'll be easier to add/remove them, or even take them as input:

const char* badWords[] = {"one", "two", "three"};

Then you can replace them:

for (auto& word : words) {
    if (std::find(std::begin(badWords), std::end(badWords), word) != std::end(badWords))
        word = "BLEEP";
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.