C / C ++ Как читать из стандартного ввода после того, как ввод дважды ударил подряд или после 2 новых строк - PullRequest
0 голосов
/ 25 января 2012

Я пытаюсь, чтобы пользователь ввел в консоль блок текста, который моя программа будет читать из стандартного ввода только после того, как ввод был дважды нажат подряд или, по-другому, когда ввод нажал на уже пустая строка. Но я хочу продолжить чтение из stdin, поэтому, в основном, читать из stdin только тогда, когда нажата клавиша enter, когда она уже пуста. Затем промойте и перезапустите.

Пример ввода пользователя:

Hello(\n)
World(\n)
(\n)
(Read Now)

Мне не удалось найти функцию ввода, способную указать это поведение.

Кроме того, я пробовал несколько методов, использующих функции поиска одного символа, но я не смог заставить его работать правильно.

Кто-нибудь знает способ сделать это элегантно?

Ответ реализован:

char word[100];
int i = 0;
while ((word[i++] = getchar())!='\n' || (word[i++]=getchar())!='\n');
printf("%s",word);

Очевидно, что переполнение буфера необходимо устранить перед использованием. Просто пример.

Ответы [ 3 ]

2 голосов
/ 25 января 2012

Игнорировать все, пока вы не прочитаете пустую строку, затем прекратите игнорировать.

// Untested code
std::string s;
// Ignore first block
while(std::getline(std::cin, s) && !s.empty()) {
  /* nothing */
  ;
}
// Don't ignore the second block
while(std::getline(std::cin, s)) {
  std::cout << "You typed: " << s << "\n";
}
2 голосов
/ 25 января 2012

Как правило, вы хотите игнорировать ввод до последовательности \n\n.Вы можете сделать это с:

while (getchar()!='\n' || getchar()!='\n');
//read the input now
0 голосов
/ 25 января 2012

Вы можете создать буфер потока фильтрации, который будет читать строки по мере их поступления, но блокирует пересылку символов до тех пор, пока он не увидит две строки. Затем он может притвориться, что это все, чего можно ожидать, пока что-то не сбросит его. Код будет выглядеть примерно так:

class blockbuf: public std::streambuf {
public:
    blockbuf(std::streambuf* sbuf): sbuf_(sbuf), blocked_(false) {}
    int underflow() {
        std::istream in(this->blocked_? 0: this->sbuf);
        for (std::string line; std::getline(in, line) && !line.empty(); ) {
             this->buffer_ += line + "\n";
        }
        if (this->in_) {
            this->buffer_ += "\n";
        }
        this->setg(this->buffer_.c_str(), this->buffer_.c_str(),
                   this->buffer_.c_str() + this->buffer_.size());
        this->blocked_ = true;
        return this->gptr() == this->egptr()
             ? traits_type::eof()
             : traits_type::to_int_type(*this->gptr());
    }
    void unblock() { this->blocked_ = false; }

private:
    std::streambuf* sbuf_;
    bool            blocked_;
    std::string     buffer_;
};

Вы бы использовали этот потоковый буфер примерно так (если вы хотите использовать его через std::cin, вы можете использовать std::cin.rdbuf() для замены std::cin потокового буфера):

blockbuf b(std::cin.rdbuf());
std::istream in(&b);
for (std::string block; std::getline(in, block, 0); b.unblock(), in.clear()) {
     processAllLinesUpToEmptyLine(block);
}

Очевидно, существует множество вариантов, как играть в эту игру ...

...