在main()中的一行中初始化/设置char * argv []

时间:2014-01-02 07:29:43

标签: c++ main argv

我想在char *argv[]内初始化/设置main(),以便我稍后可以在我的计划中使用argv[1], argv[2]...


到目前为止,我知道如何以两种方式做到这一点:

  1. 对于int main(),请使用以下一行:

    int main()
    {
        char *argv[] = {"programName", "para1", "para2", "para3", NULL};
    }
    

    请注意,最后使用NULL是因为argv数组中的指针指向C字符串,根据定义NULL终止。

  2. 对于int main(int argc, char* argv[]),我必须使用多行:

    int main(int argc,char* argv[])
    {
        argv[0] = "programName";
        argv[1] = "para1";
        argv[2] = "para2";
        argv[3] = "para3";
    }
    
  3. 我的问题是如何将这两种方法结合起来,即只使用一行来为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[]设置)。

3 个答案:

答案 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的基础。