【问题标题】:C/C++ How to read from stdin after enter is hit twice in a row or after 2 newlinesC / C ++如何在输入连续两次或两次换行后从标准输入读取
【发布时间】:2012-01-24 23:36:00
【问题描述】:

我试图让用户在控制台中输入一段文本,我的程序只有在连续两次按下 enter 后才会从 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);

显然在使用这个之前需要处理缓冲区溢出。只是一个例子。

【问题讨论】:

  • 逐行读取并在读取空行时设置标志。
  • “刷新并重新启动”是什么意思?你指定的程序的语义真的很差。

标签: c++ c input stdin


【解决方案1】:

基本上,您希望在序列\n\n 之前忽略输入。你可以这样做:

while (getchar()!='\n' || getchar()!='\n');
//read the input now

【讨论】:

  • 美丽、简短、简单。我想有一种比我想出的冗长解决方案更好的方法。
【解决方案2】:

在你读到一个空白行之前忽略所有内容,然后停止忽略。

// 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";
}

【讨论】:

    【解决方案3】:

    您可以创建一个过滤流缓冲区,它在行进入时读取行,但阻止转发字符,直到它看到两个换行符。然后它可以假装这就是预期的一切,直到某些东西重置它。代码看起来像这样:

    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);
    }
    

    显然,如何玩这个游戏有很多变化......

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-16
      • 2020-03-07
      • 2021-08-03
      • 2020-02-25
      • 2012-03-19
      • 2013-07-31
      • 1970-01-01
      相关资源
      最近更新 更多