将std :: string转换为char * const *的数组

时间:2015-06-03 07:40:56

标签: c++ string shell vector posix

我正在使用POSIX api在C ++中编写命令shell,并遇到了麻烦。我正在通过execvp(3)执行,所以我不知何故需要将包含该命令的std :: string转换为可以传递给的一个合适的char * consts *数组:

int execvp(const char *file, char *const argv[]);

我已经绞尽脑汁待了几个小时,但我想不出任何现实或理智的方式来做这件事。任何有关如何实现此转换的帮助或见解将不胜感激。谢谢你,祝你有个美好的一天!

编辑: 根据Chnossos的要求,这是一个例子:

const char *args[] = {"echo", "Hello,", "world!"};
execvp(args[0], args);

6 个答案:

答案 0 :(得分:4)

假设您的字符串包含多于&#34;一个参数&#34;,您首先必须拆分字符串(使用std::vector<std::string>将用于存储单独的字符串),然后为每个字符串向量中的元素,将该字符串的.c_str()存储到const char args[MAXARGS] [或std::vector<const char*> args;中,如果您不介意使用C ++ 11,请使用args.data() ]。不要忘记在最后一个元素中存储0nullptr

至关重要的是,如果你使用c_str表示你所依据的字符串不是暂时的:const char* x = str.substr(11, 33).c_str();不会给你你想要的东西,因为在那一行的末尾,临时字符串被销毁,其存储空间被释放。

如果您只有一个实际参数,

const char* args[2] = { str.c_str(), 0 }; 

会奏效。

答案 1 :(得分:0)

示例性方法:

#include <string>
#include <vector>
#include <cstring>

using namespace std;

int execvp(const char *file, char *const argv[]) {
   //doing sth
}

int main() {

   string s = "echo Hello world!";
   char* cs = strdup(s.c_str());
   char* lastbeg = cs;
   vector<char *> collection;
   for (char *itcs = cs; *itcs; itcs++) {
      if (*itcs == ' ') {
          *itcs = 0;
          collection.push_back(lastbeg);
          lastbeg = itcs + 1;
      }
   }
   collection.push_back(lastbeg);
   for (auto x: collection) {
       printf("%s\n", x);
   }
   execvp("abc.txt", &collection[0]);

}

请注意,此处未释放cs的内存...在您的应用程序中,您需要处理该内存...

可以从collection.size()

中简单地提取数组中的元素数

答案 2 :(得分:0)

我用这个:

command_line.hpp:

#pragma once

#include <vector>
#include <string>

namespace wpsc { namespace unittest { namespace mock {

    class command_line final
    {
    public:
        explicit command_line(std::vector<std::string> args = {});
        explicit command_line(int argc, char const * const * const argv);

        int argc() const;

        /// @remark altering memory returned by this function results in UB
        char** argv() const;

        std::string string() const;
    private:
        std::vector<std::string> args_;
        mutable std::vector<char*> c_args_;
    };

}}} // wpsc::unittest::mock

command_line.cpp:

#include <wpsc/unittest/mock/command_line.hpp>

#include <algorithm>
#include <sstream>

namespace wpsc { namespace unittest { namespace mock {

    command_line::command_line(std::vector<std::string> args)
    : args_( std::move(args) ), c_args_( )
    {
    }

    command_line::command_line(int argc, char const * const * const argv)
    : command_line{ std::vector<std::string>{ argv, argv + argc } }
    {
    }

    int command_line::argc() const
    {
        return static_cast<int>(args_.size());
    }

    char ** command_line::argv() const
    {
        if(args_.empty())
            return nullptr;
        if(c_args_.size() != args_.size() + 1)
        {
            c_args_.clear();
            using namespace std;
            transform(begin(args_), end(args_), back_inserter(c_args_),
                [](const std::string& s) { return const_cast<char*>(s.c_str()); }
            );
            c_args_.push_back(nullptr);
        }
        return c_args_.data();
    }

    std::string command_line::string() const
    {
        using namespace std;
        ostringstream buffer;
        copy(begin(args_), end(args_), ostream_iterator<std::string>{ buffer, " " });
        return buffer.str();
    }

}}} // wpsc::unittest::mock

客户代码:

int main(int argc, char** argv)
{
    wpsc::unittest::mock::command_line cmd1{ argc, argv };
    // wpsc::unittest::mock::command_line cmd2{ {"app.exe" "-h"} };

    some_app_controller c;
    return c.run(cmd1.argc(), cmd1.argv());
}

答案 3 :(得分:0)

如果解析实际上真的很复杂,我会选择类似的东西:

std::string cmd = "some really complicated command here";
char * const args[] =
{
    "sh",
    "-c",
    cmd.c_str(),
    (char *) NULL
};
execvp(args[0], args);

答案 4 :(得分:0)

所以问题是将行拆分为单独的参数,并用相应的指针填充参数向量?

假设您要在行中的空白处拆分,则使用空字节(就地)替换字符串中的空格。然后,您可以使用指针填充参数向量。

你必须编写一个循环来完成字符串。

答案 5 :(得分:-2)

您需要确定shell的规则并实施它们。这是制作炮弹工作的重要部分。

您需要编写此代码,并不简单。在典型的shell中,echo "Hello world!"必须变为{echoHello world!},而echo \"Hello world!\"必须变为{echo"Hello world!"}。等等。

你的shell会"做什么? '会做什么?在编写此部分之前,您需要做出这些决定。