我正在为我的操作系统类工作。我们可以选择使用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 ++。
感谢大家的时间。
答案 0 :(得分:3)
如果您将参数放入std::vector<std::string>
中,就像在C ++中那样,那么您需要进行小规模转换才能获得execvp
想要的char **。幸运的是,std::vector
和std::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 ++中的string
。 string
类有一个构造函数,它接受C-string:
char str[] = "a string";
string cppStr(str);
现在,您可以使用C ++中的string
类来操作字符串。