需要在C ++中使用char **而不是std :: string *

时间:2016-01-17 21:28:28

标签: c++ c arrays string char

我正在为我的操作系统类工作。我们可以选择使用C或C ++,所以我决定使用C ++,因为我最近在C上练习它比C语言更快。

我需要打电话(来自" $ man execvp "在Linux上)

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

(除非我弄错了)意味着我需要一个C风格的char *数组(C中的字符串数组),并且无法使用C ++中的std :: string。

我的问题是:在C ++中使用char *数组而不是字符串数组的正确方法是什么?大多数人倾向于说C ++中不再使用malloc(我现在尝试了一些并发症)

char** cmdList = (char**)malloc(128 * sizeof(char*));

但我不知道如何制作char *数组。 即使我使用C ++,我仍然可以解决这个问题吗?我还没有遇到过我无法使用字符串的情况C ++。

感谢大家的时间。

6 个答案:

答案 0 :(得分:3)

如果您将参数放入std::vector<std::string>中,就像在C ++中那样,那么您需要进行小规模转换才能获得execvp想要的char **。幸运的是,std::vectorstd::string在记忆中都是连续的。但是,std::vector<std::string>不是指针数组,因此您需要创建一个指针。但你也可以使用vector

// given:
std::vector<std::string> args = the_args();
// Create the array with enough space.
// One additional entry will be NULL to signal the end of the arguments.
std::vector<char*> argv(args.size() + 1);
// Fill the array. The const_cast is necessary because execvp's
// signature doesn't actually promise that it won't modify the args,
// but the sister function execlp does, so this should be safe.
// There's a data() function that returns a non-const char*, but that
// one isn't guaranteed to be 0-terminated.
std::transform(args.begin(), args.end(), argv.begin(),
  [](std::string& s) { return const_cast<char*>(s.c_str()); });

// You can now call the function. The last entry of argv is automatically
// NULL, as the function requires.
int error = execvp(path, argv.data());

// All memory is freed automatically in case of error. In case of
// success, your process has disappeared.

答案 1 :(得分:1)

而不是malloc使用new[]

char ** cmdlist = new char*[128];

不需要sizeof,因为new知道它创建的类型的大小。对于类,如果它存在,它也会调用默认构造函数。但要小心:如果某个类型没有(公共)默认构造函数,则无法使用new[]

而不是free使用delete[]在完成后释放你的记忆:

delete[] cmdlist;

当然,您也可以使用vector。这样做的好处是,当矢量被破坏时,用于存储矢量内容的内存会自动释放。

#include <vector>
...
std::vector<char*> cmdlist(128, nullptr);   // initialize with nullpointers
// access to entries works like with arrays
char * firstCmd = cmdList[0];
cmdlist[42] = "some command";
// you can query the size of the vector
size_t numCmd = cmdlist.size();
// and you can add new elements to it
cmdlist.push_back("a new command");
...
// the vector's internal array is automatically released
// but you might have to destroy the memory of the char*s it contains, depending on how they were created
for (size_t i = 0; i < cmdlist.size(); ++i)
    // Free cmdlist[i] depending on how it was created.
    // For example if it was created using new char[], use delete[].

答案 2 :(得分:1)

假设您有一个代表参数列表的std::vector<std::string> args变量,您可以执行以下操作来获取C样式的字符串数组:

auto argvToPass = std::make_unique<const char*[]>(args.size() + 1);
int i = 0;
for (const auto& arg : args)
{
    argvToPass[i++] = arg.c_str();
}

// make we have a "guard" element at the end
argvToPass[args.size()] = nullptr;

execvp(yourFile, argvToPass.get());

答案 3 :(得分:0)

您可以使用const char*创建一个string.c_str()数组并仍使用字符串,代码将如下所示

const char ** argv  = new const char*[128];
string arg1 = "arg";
argv[0] = arg1.c_str();

答案 4 :(得分:0)

如果你想得到它的花哨(和安全),你可以使用std::unique_ptr以达到良好效果,以确保在发生错误或异常时正确删除/释放所有内容:

// Deleter to delete a std::vector and all its
// malloc allocated contents
struct malloc_vector_deleter
{
    void operator()(std::vector<char*>* vp) const
    {
        if(!vp)
            return;

        for(auto p: *vp)
            free(p);

        delete vp;
    }
};

// self deleting pointer (using the above deleter) to store the vector of char*
std::unique_ptr<std::vector<char*>, malloc_vector_deleter> cmds(new std::vector<char*>());

// fill the vector full of malloc'd data
cmds->push_back(strdup("arg0"));
cmds->push_back(strdup("arg1"));
cmds->push_back(strdup("arg2"));

// did any of the allocations fail?
if(std::find(cmds->begin(), cmds->end(), nullptr) != cmds->end())
{
    // report error and return
}

cmds->push_back(nullptr); // needs to be null terminated

execvp("progname", cmds->data());

// all memory deallocated when cmds goes out of scope

答案 5 :(得分:-1)

  

(除非我弄错了)意味着我需要一个C风格的char *数组(C中的字符串数组),并且无法使用C ++中的std :: string。

不,您仍然可以使用C ++中的stringstring类有一个构造函数,它接受C-string:

char str[] = "a string";
string cppStr(str);

现在,您可以使用C ++中的string类来操作字符串。