我想在char *argv[]
内初始化/设置main()
,以便我稍后可以在我的计划中使用argv[1], argv[2]...
。
到目前为止,我知道如何以两种方式做到这一点:
对于int main()
,请使用以下一行:
int main()
{
char *argv[] = {"programName", "para1", "para2", "para3", NULL};
}
请注意,最后使用NULL
是因为argv
数组中的指针指向C字符串,根据定义NULL
终止。
对于int main(int argc, char* argv[])
,我必须使用多行:
int main(int argc,char* argv[])
{
argv[0] = "programName";
argv[1] = "para1";
argv[2] = "para2";
argv[3] = "para3";
}
我的问题是如何将这两种方法结合起来,即只使用一行来为int main(int argc, char* argv[])
初始化它?特别是,我希望能够这样做(目前这将是错误的):
int main(int argc, char* argv[])
{
argv = {"programName", "para1", "para2", "para3", NULL};
}
我怎样才能做到这一点?
修改:我知道可以在argv[]
中设置Debugging Command Arguments
。我想在main()
中编辑它们的原因是,我不想每次都使用Debugging Command Arguments
来处理新的测试用例(不同的argv[]
设置)。
答案 0 :(得分:7)
最安全的方法可能是不写入argv引用的内存,(可能没有按照你的想法构建),但是有另一个批量:
int main(int argc, const char** argv)
{
const char* n_argv[] = { "param0", "param1", "param2" };
argv = n_argv;
...
}
这会分散argv从原始内存(由调用者拥有,仍然存在)转移到另一个将在main()的生命周期中存在的内容。
请注意,const char*
是必需的,以避免不推荐使用的“* string to char **”消息。
注意:此代码已在Linux上使用GCC 4.8.1编译,给出以下结果:
make all
Building file: ../main.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -pedantic -Wall -c -std=c++11 -o "main.o" "../main.cpp"
Finished building: ../main.cpp
Building target: e0
Invoking: GCC C++ Linker
g++ -o "e0" ./main.o
Finished building target: e0
答案 1 :(得分:3)
如果您能够使用C99,则可以使用compound literals功能。这是一个在编译为gcc -std=c99 main.c
时似乎有用的示例:
#include <stddef.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
argv = (char *[]){"programName", "para1", "para2", "para3", NULL};
char **p = argv;
argc = 0;
while (*p++ != NULL) {
argc++;
}
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
}
答案 2 :(得分:3)
让我们假设您的程序采用一组字符串并对其执行某些操作。让我们称它为process_strings
,需要进行测试。您希望为不同的测试用例传递不同的字符串集,例如{"abc", "efg", "hij"}
,{"thin", "run", "win"}
,{"cat", "rat", "mat"}
等。将来您希望在不更改原始函数的情况下添加更多此类测试用例{ {1}}。然后,解决此问题的正确方法是修改(驱动程序)程序,以便您不必为添加/删除的不同测试用例重新编译。一个例子可能是:
process_strings
测试用例文件示例#include <fstream>
#include <iostream>
#include <string>
#include <memory>
#include <sstream>
#include <vector>
#include <iterator>
// tested function
void process_strings(const std::vector<std::string>& params)
{
for (auto iter = params.cbegin(); iter < params.cend(); ++iter)
std::cout << *iter << '\t';
}
// driver program
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cout << "Insufficient data" << std::endl;
return -1;
}
std::ifstream test_file(argv[1]); // pass test cases file as an argument
std::string test_case;
while (std::getline(test_file, test_case))
{
// each line is a test case
std::istringstream iss(test_case);
std::vector<std::string> params;
// break parameters separated by ' ' blankspace
copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(params));
// if there're valid parameters, then pass it to the tested function
if (!params.empty())
{
process_strings(params);
std::cout << std::endl;
}
}
}
:
tests.txt
为abc efg
cat rat mat
animal man
生成的输出:
C:\> simple.exe tests.txt
如果您的参数包含空格,即如果空格不能用作分隔符,请参阅this post有关如何从该行中提取参数的信息。
因此我们将输入数据与代码分开。每次测试用例发生变化时,都不需要重新编译程序。只需更改输入,通过已编译的程序运行它并验证输出。这节省了大量的开发时间,在某种意义上也是data-driven programming的基础。