在C ++中使用istringstream [英] Using istringstream in C++

查看:84
本文介绍了在C ++中使用istringstream的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些利用fork,execlp和等待进行两个处理的代码.目的是能够重复打印提示并让用户输入一个命令,该命令最多包含4个参数/选项.

I have some code that utilizes fork, execlp, and wait to make two processes. The objective is to be able to repeatedly print a prompt and have the user enter a command with up to 4 arguments/options to the command.

int main()
{
     string command, argument;
     istringstream iss(argument);

  do
  {
  //prompt user for command to run
  cout << "Enter command: ";
  cin >> command >> argument;

  int pid, rs, status;

  //fork will make 2 processes
  pid = fork();
  if(pid == -1) { perror("fork"); exit(EXIT_FAILURE); }

if(pid == 0) {
//Child process: exec to command with argument

//C_str to get the character string of a string
rs = execlp(command.c_str(), command.c_str(), argument.c_str(), (char*) NULL);
.
if (rs == -1) { perror("execlp"); exit(EXIT_FAILURE); }
} else {
   //Parent process: wait for child to end
   wait(&status);
      }
   } while(command != "exit");

   return 0;
}

我知道当前的代码只能支持该命令的一个参数,但是我不确定要使用什么来指定1到4个参数.那是当我一个朋友向我提及std::istringstream时,但是在研究它时,我不知道如何在程序的其余部分中将其用于输入.有没有办法设置它,或者有其他方法可以用来满足要求?

I knew that the current code I have would be able to support only one argument to the command, but I wasn't sure about what to use in order to specify between 1 to 4 arguments. That's when I a friend mentioned to me about std::istringstream, but while looking into it, I didn't understand how to use it for input with the rest of the program. Is there a way to set it up or is there a different method to use to fulfill the requirements?

推荐答案

使用用户输入的std::istringstream的最常见用法模式是接受一行文本,然后对其进行处理.这样可以避免在输入与您期望的输入不匹配或无法预测时可能发生的问题.

The most common usage pattern for std::istringstream with user input is to accept a single line of text and then process it. This avoids problems that can occur when the input does not match what you expect, or cannot be predicted.

这是一个简单的示例,它一次从STDIN读取一行,然后将其处理为命令,然后是字符串向量作为参数.

Here is a simple example that reads one line at a time from STDIN, and processes it into a command followed by a vector of strings as arguments.

for(std::string line; std::getline(std::cin, line); )
{
    std::istringstream iss(line);

    std::string command;
    if (iss >> command)
    {
        std::vector<std::string> args;
        for (std::string arg; iss >> arg; )
        {
            args.push_back(arg);
        }
        std::cout << "Received '" << command << "' with " << args.size() << " arguments\n";
    }
    else
    {
        std::cerr << "Invalid input" << std::endl;
    }
}

当然,您不需要读入字符串,也不需要将内容存储在向量中.这只是出于说明目的.

Of course, you don't need to read into strings, or store stuff in a vector. This was simply for illustrative purposes.

基本要点是避免人们遇到的陷阱,其中最常见的是期望先前的流操作成功.如果这个假设是错误的,那么天真的程序员可能会发现自己正在尝试解析应该在上一行中处理过的内容.

The basic point is to avoid pitfalls that people come up against, the most common of which is expecting the previous stream operation to have succeeded. When that assumption is false, the naive programmer can find themselves attempting to parse something that was supposed to be handed in the previous line.

残破的示例:

Broken example:

#include <iostream>

int main() {
    std::string command;
    while (std::cin >> command)
    {
        std::cout << "Got command: " << command << std::endl;
        if (command == "foo")
        {
            // 'foo' expects two integer arguments:
            int arg1, arg2;
            std::cin >> arg1 >> arg2;
            std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
        }
        else if (command == "bar")
        {
            // 'bar' expects one float argument:
            float arg1;
            std::cin >> arg1;
            std::cout << command << ": " << arg1 << std::endl;
        }
    }
    return 0;
}

在上面,假设用户感到困惑,并使用一个float参数调用" foo 命令,那么下一个命令是有效的 bar 命令:

In the above, let's say the user gets confused and "invokes" the foo command with one float argument, then the next command is a valid bar command:

foo 42.0
bar 3.14

发生的事情是这样:

  1. foo 处理程序将arg1读取为42,然后无法读取下一个参数.流现在有错误.

  1. The foo handler reads arg1 as 42, then fails to read the next argument. The stream is now in error.

在该处理程序期间未对输入进行任何错误检查,因此现在存在不确定的行为,输出arg2的值.

No error checking was done on the input during that handler, so there's now undefined behavior outputting the value of arg2.

当尝试读取下一条命令时,流已经处于错误状态,因此循环终止.

When attempting to read the next command, the stream is already in an error state and so the loop terminates.

因此,该程序的输出可能类似于:

So, the output of that program might look like:

Got command: foo
foo: 42, -149017896

可以在没有istringstream的情况下解决此问题,但这很痛苦.流可能会进入错误状态的原因有很多,而清除特定错误状态的错误标志只是为了解决此问题,这会导致代码丑陋且可能容易出错.您不仅需要清除错误标志,而且还需要告诉流忽略该行中的所有剩余字符.而且您可能已经不知道就开始阅读 next 行.

Fixing this problem without istringstream is possible, but it's a pain. There are many reasons why a stream might enter an error state, and clearing error flags for specific error states just to get around this problem makes for ugly and potentially error-prone code. Not only would you need to clear the error flags, but you would also need to tell the stream to ignore any remaining characters in the line. And you may have already started reading into the next line without knowing.

更强大的示例:

More robust example:

#include <iostream>
#include <sstream>

int main() {
    std::string command;
    for (std::string line; std::getline(std::cin, line); )
    {
        std::istringstream iss(line);
        if (!(iss >> command))
            continue;
        std::cout << "Got command: " << command << std::endl;
        if (command == "foo")
        {
            // 'foo' expects two integer arguments:
            int arg1, arg2;
            if (iss >> arg1 >> arg2)
            {
                std::cout << command << ": " << arg1 << ", " << arg2 << std::endl;
            }
        }
        else if (command == "bar")
        {
            // 'bar' expects one float argument:
            float arg1;
            if (iss >> arg1)
            {
                std::cout << command << ": " << arg1 << std::endl;
            }
        }
    }
    return 0;
}

现在,与上一个示例相同的输入将给出输出:

Now, the same input from the previous example will give the output:

Got command: foo
Got command: bar
bar: 3.14

区别是:

  • 使用istringstream,处理输入的任何错误都不会影响源流,因此上一行的故障不会导致问题.

  • Using istringstream, any errors processing our input did not affect the source stream, so a failure on the previous line does not cause problems.

在读取参数时正确检查了字符串流,从而允许进行可选的错误处理.

The string stream is correctly checked when reading arguments, allowing optional error handling.

如果在某些解析失败后,您决定尝试以不同方式处理一行输入,那么使用另一个字符串流则很容易.

If, after some parsing failure, you decide to try processing a line of input differently, that's easy to do with another string stream.

这篇关于在C ++中使用istringstream的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆