0

I'm trying to write a piece of code that "bleeps" out certain words. I've achieved this, but when attempting to stop the window from closing my cin gets ignored. I'm using "Programming: Principles and Practices Using C++" as a guide.

my code:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;


int main()
{
vector <string> words;
vector <string> bad_words = {"bad", "heck"};

cout << "When you are finished entering words press enter then Control Z." << '\n';
for (string single_word; cin >> single_word;) // read white space seperated words
   words.push_back(single_word); // puts it in the vector 

for (int i = 0; i < words.size(); ++i) {
    if (find(bad_words.begin(), bad_words.end(), words[i]) 
    != bad_words.end()) //reads through the vector searching for word i
        cout << "BLEEP!" << '\n';
    else {
        cout << words[i] << '\n';
    }
}
char stop;
cin >> stop;
}

to expand: It doesn't work when executing the program from visual studio or when executing the program by manually clicking on it.

  • Try adding `std::cin.ignore()` before the last `cin` statement. – Philip Nelson May 05 '19 at 18:57
  • adding std::cin.ignore() did not fix the problem. The prompt for the input still didn't show up. – Alexander Winslow May 05 '19 at 19:02
  • @AlexanderWinslow Which OS? Which terminal? – Swordfish May 05 '19 at 19:05
  • The OS is windows. – Alexander Winslow May 05 '19 at 19:06
  • @AlexanderWinslow Then one of the problems is that `std::cin` has the `eofbit` set after `Ctrl+Z` which must be cleard before you can read again. – Swordfish May 05 '19 at 20:02
  • Side note: Have you tried the *VS Developers Command Prompt*? For small sources like this, you can compile 20 in the time it takes to setup one VS project. (you can keep all your class source files in a single directory and compile any one with a few keystrokes). More info at the end of the answer to [This Question](https://stackoverflow.com/questions/55996112/how-to-read-data-as-characters-from-a-text-file-and-then-divide-each-character-b) – David C. Rankin May 05 '19 at 21:49
  • @DavidC.Rankin I don't believe I have. I'll look into it. Thanks for the help! – Alexander Winslow May 05 '19 at 22:57

1 Answers1

0

operator>> ignores leading whitespace, which includes line breaks. So your reading loop won't end until CTRL-Z is typed, and then the subsequent attempt to read a char at the end of the program won't have anything to read.

You should instead use std::getline() to read the user's input up to the line break, then you can use a std::istringstream to read the words from the read input, eg:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

int main()
{
    vector<string> words;
    vector<string> bad_words = {"bad", "heck"};
    string line;

    cout << "When you are finished entering words press enter then Control Z." << '\n';

    getline(cin, line);
    istringstream iss(line); 

    for (string single_word; iss >> single_word;) // read white space seperated words
        words.push_back(single_word); // puts it in the vector

    for (int i = 0; i < words.size(); ++i)
    {
        if (find(bad_words.begin(), bad_words.end(), words[i]) != bad_words.end()) //reads through the vector searching for word i
            cout << "BLEEP!" << '\n';
        else
            cout << words[i] << '\n';
    }

    char stop;
    cin >> stop;

    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • The newline could be simply ignored. I'm not a big fan of extracting from one stream zust to shove it in another. The other problem is that the stream is EOF after `Ctrl+Z`. std::cin.clear() to the rescue. – Swordfish May 05 '19 at 20:01
  • adding cin.clear() fixed the problem. Thanks! @Swordfish Could you expand on this: " I'm not a big fan of extracting from one stream zust to shove it in another." – Alexander Winslow May 05 '19 at 20:36
  • @Swordfish "*The newline could be simply ignored*" - except that `operator>>` does not stop reading on line breaks. Hence my suggestion to use `getline()` instead – Remy Lebeau May 05 '19 at 21:40
  • @Swordfish meaning, a line break is treated as whitespace and doesn't put the stream into a state where the reading loop stops due to eof/error. Your own example proves that. If you use `operator>>` to read words, you would have to peek the stream to detect line breaks manually. Using `getline()` instead avoids having to do that. – Remy Lebeau May 05 '19 at 22:31
  • @RemyLebeau Then I misunderstood you at first. – Swordfish May 05 '19 at 22:52