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

200_success
145k22 gold badges190 silver badges478 bronze badges
asked Nov 21, 2017 at 17:12
\$\endgroup\$
1
  • 8
    \$\begingroup\$ Just try not to make any clbuttic mistakes. \$\endgroup\$ Commented Nov 21, 2017 at 19:10

3 Answers 3

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.

Toby Speight
87.2k14 gold badges104 silver badges322 bronze badges
answered Nov 21, 2017 at 17:22
\$\endgroup\$
2
  • \$\begingroup\$ Thanks for the valuable review. Could you please give suggestion about the container I should use for this purpose. \$\endgroup\$ Commented Nov 22, 2017 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\$ Commented Nov 22, 2017 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!

answered Nov 21, 2017 at 20:15
\$\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";
}
answered Nov 21, 2017 at 23:03
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.