Проблема заключается в том, что:
cin >> input;
приведет к тому, что плохой бит будет установлен, когда вы попытаетесь прочитать не числовое значение. После этого любая попытка использовать operator>>
молча игнорируется.
Итак, способ исправить это - проверить, находится ли поток в хорошем состоянии, а если нет, то сбросить флаги состояния и попробовать и читать снова. Но обратите внимание, что плохой ввод (который вызвал проблему) по-прежнему находится на входе, поэтому вам нужно также убедиться, что вы выбрасываете его.
if (cin >> input)
{
// It worked (input is now in a good state)
}
else
{
// input is in a bad state.
// So first clear the state.
cin.clear();
// Now you must get rid of the bad input.
// Personally I would just ignore the rest of the line
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// now that you have reset the stream you can go back and try and read again.
}
Чтобы предотвратить его застревание (что вызвано установленный неверный бит), считывается в строку, затем используется строковый поток для анализа ввода пользователя. Я также предпочитаю этот метод (для пользовательского интерактивного ввода), поскольку он позволяет упростить сочетание разных стилей чтения (т.е. комбинировать operator>>
и std::getline()
, как вы можете использовать их в потоке строк).
#include <iostream>
#include <sstream>
#include <string>
// using namespace std;
// Try to stop using this.
// For anything other than a toy program it becomes a problem.
int main(int argc, char *argv[])
{
int input;
std::string line;
while(std::getline(std::cin, line)) // read a line at a time for parsing.
{
std::stringstream linestream(line);
if (!(linestream >> input))
{
// input was not a number
// Error message and try again
continue;
}
if ((input < 1) || (input > 3))
{
// Error out of range
// Message and try again
continue;
}
char errorTest;
if (linestream >> errorTest)
{
// There was extra stuff on the same line.
// ie sobody typed 2x<enter>
// Error Message;
continue;
}
// it worked perfectly.
// The value is now in input.
// So break out of the loop.
break;
}
}
Вы звоните onDestroy()
еще до создания цепочки с takeUntil
.
Когда вы в конце концов позвоните printFoo()
, предыдущие выбросы unsubscribe
не будут переизданы, а субъект unsubscribe
уже завершен, поэтому takeUntil
в этом случае никогда не завершит цепочку.
Поскольку Субъект излучает до подписки printFoo
.
После подписки больше нет Тематических излучений.
Вместо этого вы можете использовать BehaviorSubject, поскольку он содержит излучаемые значения (последнее излученное значение):
const unsubscribe = new BehaviorSubject(false);
function printFoo() {
of('foo')
.pipe(takeUntil(unsubscribe.pipe(filter(value => !!value)))) // Don't unsub if it's false emitted
.subscribe(console.log)
}
function onDestroy() {
unsubscribe2.next(true); // Emit true to cancel subscription
}