多次从 std::cin 读取 -- Linux 和 Mac OS X 上的行为不同

Reading from std::cin multiple times -- different behavior on Linux and Mac OS X

本文关键字:OS Mac std cin 读取 Linux      更新时间:2023-10-16

我想从标准输入中读取一些数字,处理它们,然后读取下一组数字。

我想出了在char中读取EOF字符并清除 eofbit、failbit 和 badbit 的解决方案。以下代码适用于带有GCC 4.9.2的Ubuntu 14.04:

#include <iostream>
#include <vector>
int main() {
    std::vector<double> a;
    std::vector<double>::iterator it;
    double x;
    while(std::cin >> x) {
        a.push_back(x);
    }
    std::cout << "First bunch of numbers:" << std::endl;
    for (it = a.begin(); it != a.end(); ++it) {
        std::cout << *it << std::endl;
    }
    // get crap out of buffer
    char s;
    std::cin >> s;
    std::cin.clear();
    // go for it again
    while (std::cin >> x) {
        a.push_back(x);
    }
    std::cout << "All the numbers:" << std::endl;
    for (it = a.begin(); it != a.end(); ++it) {
        std::cout << *it << std::endl;
    }
    return 0;
}

因此,在 Ubuntu 上,我可以键入 1<Return>2<Return>^D ,获取一些输出,键入 3<Return>4<Return>^D ,获取更多输出,程序终止。

但是,在Mac OS 10.10上,使用相同的GCC版本,程序将不接受第二轮输入,而是在第一次点击^D后两次输出第一个数字序列。

  • 为什么会出现不一致的行为?是否有可能解决它?
  • 接受两次输入的惯用方法是什么?
  • 在我的用例中,第一堆数字最终可能会从文件或管道中读取。在这种情况下,我如何以交互方式请求其他输入。

我不是那么熟悉,但是,这家伙有一个类似的问题: Mac osx 终端中的信号 EOF

默认情况下,OS X(以前称为 Mac OS X)终端可在行首按下 control-D 时识别 EOF。

具体来说,实际操作是,当按下 control-D 时, 终端输入缓冲区中的所有字节都发送到正在运行的 使用终端进行处理。在一行的开头,没有字节 缓冲区,因此进程被告知有零字节可用,并且 这充当 EOF 指标。

此过程兼作向流程传递输入的方法 在行尾之前:用户可以键入一些字符并按 control-D,字符将立即发送到进程, 无需通常等待输入/返回被按下。在此之后 执行"立即发送所有缓冲字节"操作,无字节 留在缓冲区中。因此,当第二次按下 control-D 时, 它与一行的开头相同(不发送字节,并且 进程被赋予零字节),它的作用类似于 EOF。

您可以使用命令"man 4 tty"在终端中。默认行规则是termios。您可以 通过使用命令"man 特米奥斯"。

埃里克·波皮希尔的接受答案

我没有OSX可以测试,但也许这可以解释行为