如何防止'std::cin'或'\n'刷新'std::cout'的缓冲区?

How to prevent `std::cin` or `\n` from flushing the buffer of `std::cout`?

提问人:Giogre 提问时间:8/24/2020 最后编辑:Giogre 更新时间:8/24/2020 访问量:502

问:

让我们想象一下,我的程序在不同时间需要用户的输入。 我希望此输入防止刷新缓冲区。 我可以在不同的流缓冲区上设置 和 吗?coutcincout

有问题的示例:一个程序,它读取一行中的两个数字,并且取决于第一个数字是 、 或:n1 n2012

  • n1 = 0:将第二个数字写入向量n2v
  • n1 = 1:输出v[n2]cout
  • n1 = 2:上pop_back()v

MWE是:

#include <iostream>
#include <vector>

using namespace std;

int main() {
    int size, n1, n2;
    vector<int> v;
    cin >> size;

    while(size--){
        cin >> n1;

        if (n1 == 0)
        {
            cin >> n2;
            v.push_back(n2);
        }
        else if (n1 == 1)
        {
            cin >> n2;
            cout << v[n2] << '\n';
        }   
        else if (n1 == 2)
            v.pop_back();
    }

return 0;
}

假设我有这个测试输入

8
0 1
0 2
0 3
2
0 4
1 0
1 1
1 2

正确的输出应该是

1
2
4

上面的程序产生散布在输入行中的输出。

但我希望它们在最终程序中全部打印在一起,而无需使用不同的方式,例如将它们存储在某个容器中等。

所以我认为我应该在缓冲区上操作,但如何操作?

C++ IO IOstream streambuf

评论

1赞 Pete Becker 8/24/2020
std::endl始终刷新它插入到的流。这就是它的工作。
0赞 Remy Lebeau 8/24/2020
默认情况下,和 是在一起的,因此读取输入将首先刷新任何挂起的输出。您可以通过调用 来取消它们。cincouttie()tie()cin.tie(nullptr)
0赞 Giogre 8/24/2020
@RemyLebeau:如果有的话,解绑的副作用是什么?
1赞 Remy Lebeau 8/24/2020
@Lingo看一看 stackoverflow.com/questions/31162367
1赞 Pete Becker 8/24/2020
@Lingo -- 不,解绑并不能完成你要找的一切。它消除了交互式输入所需的强制刷新。它不会影响流的内部冲洗。举个极端的例子,如果程序写入了足够的输出来填充输出缓冲区,则下次插入流将刷新缓冲区。而且你不想禁用它。<克>

答:

0赞 David G 8/24/2020 #1

无需修改缓冲区。相反,您可以存储在第二个向量中并将其打印在循环的外部。cout << v[n2]v[n2]

评论

0赞 Giogre 8/24/2020
感谢您的及时回复。如果我不能/不想使用容器,正如我在问题正文中所说的那样,该怎么办?有没有办法防止冲洗缓冲液?cin
0赞 Eljay 8/24/2020
您可以写入自己的缓冲区,然后在准备就绪时将其输出到缓冲区。std::stringstreamstd::cout
0赞 Giogre 8/24/2020
@Eljay:我想,想用MWE进一步详细说明吗?
6赞 Eljay 8/24/2020 #2

您可以写入自己的缓冲区,然后在准备就绪时将其输出到缓冲区。std::stringstreamstd::cout

MWE:

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <vector>

using std::cin;
using std::cout;
using std::istream;
using std::runtime_error;
using std::stringstream;
using std::vector;

static auto get_int(istream& in) -> int {
    int n;
    if (!(in >> n)) {
        throw runtime_error("bad input");
    }
    return n;
}

int main() {
    auto ss = stringstream();
    auto v = vector<int>();
    auto size = get_int(cin);

    while(size--) {
        auto n1 = get_int(cin);

        if (n1 == 0) {
            auto n2 = get_int(cin);
            v.push_back(n2);
        } else if (n1 == 1) {
            auto n2 = get_int(cin);
            ss << v[n2] << '\n';
        } else if (n1 == 2) {
            v.pop_back();
        }
    }

    cout << ss.str();
}

评论

0赞 Giogre 8/24/2020
有趣的是,相当强大。为什么坚持使用的时候你可以写?我很好奇,因为这些不是一些过于复杂的自定义类型。<sstream>autoint
0赞 Eljay 8/24/2020
我更喜欢使用 ,部分原因是它需要初始化,尤其是对于基本类型。auto
0赞 Giogre 8/24/2020
也许它更安全,但它稍微混淆了代码。
1赞 Eljay 8/24/2020
我认为“混淆”更多的是陌生。一旦我习惯了它(在 C# 中使用),我发现代码更加清晰。var