getline 出错(我相信),在获取管道程序的输入时抛出 std::logic_error

Posted

技术标签:

【中文标题】getline 出错(我相信),在获取管道程序的输入时抛出 std::logic_error【英文标题】:Error with getline (I believe), throwing std::logic_error when getting input for pipe program 【发布时间】:2019-10-31 00:52:14 【问题描述】:

我正在为我的 UNIX 和网络编程课程做家庭作业,我必须重写 UNIX 管道 (|) 功能。

我尝试了多种方法,例如更改部分代码无济于事,并使用 GDB 尝试调试代码,但它并没有指向任何地方。我已经做了一些错误检查,包括在用户输入空值时退出程序(循环),但这似乎没有帮助。

// Variable declarations.
char command1[255], command2[255];
char *tok1, *tok2;
string file_path;
int pipefd[2], rs;

// Loop indefinitely.
while(1) 
    // Get user input and store it.
        // command 1
    cout << "command1? ";
    cin.getline(command1, 255);
        // tokenize the command based on space as the delimiter
    tok1 = strtok(command1, " ");
        // if user typed quit, stop the loop.
    if((string)tok1 == "quit") break;
        // if user left field blank, error and stop the loop.
    if(tok1==NULL)  cerr << "pipe: Must enter a command.\n"; break; 
        // command 2
    cout << "command2? ";
    cin.getline(command1, 255);
        // tokenize the command based on space as the delimiter
    tok2 = strtok(command2, " ");
        // if user typed quit, stop the loop.
    if((string)tok2=="quit") break;
        // if user left field blank, error and stop the loop.
    if(tok2==NULL)  cerr << "pipe: Must enter a command.\n"; break; 

...循环在管道和叉子之后结束,所有这些都完成了,缩短到我认为问题所在的地方。

以下错误不断出现,我不知道如何修复它。

command1? ls

command2?厕所

在抛出 'std::logic_error' 实例后调用终止

what(): basic_string::_M_construct null 无效

【问题讨论】:

看起来程序试图从空指针构建std::stringstrtok 用完令牌或检测到错误时返回 NULL。 那么这是否意味着 command1/command2 在某些时候为空?如果我输入命令,我不确定如何或为什么会发生这种情况。 您的第二个 getline 在应该读入 command2 时读入 command2。 嘿,我能说服你用std::getline 读入std::string,然后用std::istringstream 解析吗?类似getline(cin, command1); istringstream strm(command1); strm &gt;&gt; tok1; 哦,嘿,如果您使用的是 gdb,这里有一个针对 C++ 异常的 gdb 调试技巧。在 gdb 提示符处运行程序之前,请写入catch throw,这就像抛出异常的断点一样。我相信你也可以做到catch catch 【参考方案1】:

在第二个命令之后,您将第一个命令作为输入 getline。

变化:

cin.getline(command2, 255);
// tokenize the command based on space as the delimiter
tok2 = strtok(command1, " ");

收件人:

cout << "command2? ";
// tokenize the command based on space as the delimiter
cin.getline(command2, 255);

【讨论】:

谢谢!这解决了我的空错误。有趣的是,您错误地做某事如何成为您似乎无法弄清楚的最大问题。 我很高兴能帮上忙!【参考方案2】:

哦,是的,您的问题的直接答案是将您的 if( tok2 == NULL ) 移动到您的 (string)tok2 演员之上。

您将 char 缓冲区转换为 std::string 只是为了进行比较。

所以我假设您已经包含了字符串标题。这意味着您可以访问读入字符串的 getline。这比 char 缓冲区更容易使用和更安全。然后你已经有了一个字符串。

查看https://en.cppreference.com/w/cpp/string/basic_string/getline 并查看覆盖#2 和示例。

这也将解决您的错误,这是由于 strtok 找不到空格,返回 NULL,并且您试图从 NULL 指针中生成字符串。

【讨论】:

谢谢。我会努力的。我知道并尝试使用两者,但出于某种原因,istream 对我来说更有意义。我明白你的意思,我可能会改变它。 @triglav 哦,你可以使用cin &gt;&gt; mystring 而不是strtok 来打破空格,它会在读入std::string mystring; 时打破空白如果你先读一整行,那么你可以创建一个istringstream 从字符串中读取,就好像它是一个流一样。 @triglav 我添加了第一段,它实际上回答了你的问题。 :-)

以上是关于getline 出错(我相信),在获取管道程序的输入时抛出 std::logic_error的主要内容,如果未能解决你的问题,请参考以下文章

std::getline 卡在管道输入的末尾

从管道分隔文件中获取值

加载管道程序集时出错

管道输入出错时如何让程序返回

C ++试图通过getline函数为函数调用获取用户输入值

Azure 数据工厂 - 删除活动时出错