在程序代码中创建 argc argv

10

你好,这是一个非常初级的问题,但我就是想不明白:

我有一个名为“bar”的函数。

class foo
{
    public:
        bool bar(int argc, char** argv);
}

argv应该包含

"--dir" and "/some_path/"

我该如何创建 argv 和 argc 并将它们传递给 bar() 函数?我尝试了很多种方法,但是指针和类型转换总是有问题。
因此,我想在代码中创建 argv,而不是从命令行获取它。
谢谢任何意见!

你需要创建吗?不用!你可以通过 argv 将参数传递给程序。argc 是传入的参数数量。argv 可以保存任何值,路径等。 - Raindrop7
@Raindrop7,有时候你需要在程序内部创建argc和argv。例如,如果你想使用boost单元测试,最终会调用main函数。而在Android上(如果你想在设备上运行测试),你必须自己调用它并为其形成参数。 - Alexey Guseynov
2个回答

25

我最喜欢的方式是这样的:

std::vector<std::string> arguments = {"--dir", "/some_path"};

std::vector<char*> argv;
for (const auto& arg : arguments)
    argv.push_back((char*)arg.data());
argv.push_back(nullptr);

f.bar(argv.size() - 1, argv.data());

请注意,如果参数是静态的且不会发生改变,则这种方法有点过度。但这种方法的优点是符合RAII。它为您管理内存并在正确时删除对象。因此,如果参数列表是动态的,则这是最干净的方法。

此外,如果f.bar修改argv数组中的数据,则此代码在技术上是UB(未定义行为)。通常情况下不会出现这种情况。


1
const char *char * 的隐式转换。 - Slava
1
对于c++11,您可以使用左值引用和&arg[0]而无需任何转换。无论如何,我更喜欢使用const_cast<>而不是C风格的转换。 - Slava
1
你在 for (const auto& arg : arguemnts) 里打错字了,应该是 arguments - Ivan Kush
谢谢,伊万。我已经修复了这个错别字。 - Alexey Guseynov
从C++17开始,您可以使用std :: string :: data()的非const版本,而不是使用const-casting。 - klaus triendl
显示剩余2条评论

6

假设你希望以与传递给 main 相同的格式获取 argc 和 argv,那么可以这样调用它:

foo f;
char *args[] = {
    (char*)"--dir",
    (char*)"/some_path/",
    NULL
};
f.bar(2, args);

(注:这里假设 bar 不会修改参数字符串——如果会修改,那么你需要将参数类型从 char ** 改为 const char **

2
在C++中,从const char *转换为char *是非法的。 - Slava
段错误!argv 没有分配内存 - Raindrop7
@Slava 不是这样的。如果通过强制转换显式地进行转换,则在所有版本的C++中都是有效的。在C++11之前,转换也可以隐式执行,但仅适用于字符串字面值(本答案有)。只有修改指向的字符串的尝试是无效的。 - user743382
1
@Raindrop7 argv 是一个指针数组。该数组位于堆栈上,无需分配内存。指针是指向数据段中常量的指针。也不需要分配内存。 - Alexey Guseynov
@AlexeyGuseynov 是的,你可以将参数传递给其他函数,甚至是主函数。例如,在 winmain 中返回对 main 的调用,并将 argc 和 argv 传递给它。 - Raindrop7
试图修改字符串字面值会导致未定义的行为:它们可能存储在只读存储器中(例如.rodata),或与其他字符串字面值组合。 - etam1024

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接