在 C++ 程序中将 echo 输出通过管道传输到 cin 会导致无限循环

问题描述 投票:0回答:1

问题


我想向 C++ 程序输入十六进制字符。为此,我使用命令

echo -e "2\n\x01\x00\x01\x00" | ./program 4 /dev/stdin

输入

2\n
应转到
cin >> op
\x01\x00\x01\x00
将转到
read
函数(这就是为什么我将
4
/dev/stdin
作为程序的参数)。

这会导致奇怪的行为 - 菜单在无限循环中一遍又一遍地打印。即使简单地使用

echo -e "1\n" | ./program 4 /dev/stdin

导致相同的循环。例如,如果我跑步,

echo -e "1" | ./program 4 /dev/stdin

我仍然遇到无限循环,但这次

in case No. 1
行也被打印。

我想知道为什么会发生这种情况,如何解决这个问题 - 如何使程序正确理解我的输入。请注意,该解决方案应支持在回显中输入空字节 (

\x00
),因为这是我想要提供给
read
函数的数据的一部分(例如。

注释

  • 显然无限循环是因为我使用了无限循环,但这并不能真正解释为什么它使用来自
    echo
    的相同输入,我希望它使用它并终止或等待输入。
  • 我在SO中看到其他帖子谈论这个问题,但他们只解释了如何更改代码来解决问题。可悲的是,我控制命令行,无法更改代码
  • 我可以使用一个文件(写入和读取它,而不是使用
    echo
    stdin
    ),但我的问题是根本性的,而不是寻找解决方法(假设例如您没有权限写入除
    stdin
    之外的任何文件)。
  • 要明确 - 我想要的是
    2
    转到第一个
    cin
    调用,以及十六进制值转到
    read

代码


#include <fcntl.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
using namespace std;

int main(int argc, char* argv[]){
    size_t len;
    char* data;
    unsigned int op;

    while(1){
        cout << "1. use\n2. after\n";
        cin >> op;

        switch(op){
        case 1:
            cout << "in case No. 1" << endl;
            break;
        case 2:
            len = atoi(argv[1]);
            data = new char[len];
            read(open(argv[2], O_RDONLY), data, len);
            cout << "your data is allocated" << endl;
            break;
        default:
            break;
        }
    }
    return 0;
}
c++ linux bash hex echo
1个回答
0
投票

当您尝试在 EOF 处读取文件或管道时也不例外。它只是设置

eofbit
failbit
(和
cin
?)标志。来自cppreference

通过修改内部状态标志来发出错误信号,(3)除外,它从不设置任何标志(但应用的特定操纵器可能会设置)

如果您希望循环在发生这种情况时结束,则必须明确检查这一点。常见的习惯用法是像

那样构造循环
while (cin >> op) {
    // code
}

您还可以更明确地检查:

if (!cin.good()) {
    break;
}

发生这种情况时,它不会更新您要提取到的变量,因此它保留其先前的值。结果,您在

switch
中不断重复相同的情况,并且出现无限循环。

© www.soinside.com 2019 - 2024. All rights reserved.