【问题标题】:Access command line arguments in C++在 C++ 中访问命令行参数
【发布时间】:2017-11-17 17:02:17
【问题描述】:

是否可以在不通过 int main(int, char**) 接收的情况下获取命令行参数?我不想将参数传递给多个方法,因此全局函数将是完美的。另外,我不想通过全局变量自己存储参数。我正在运行 Windows 和 Linux。

编辑: 示例:

int main()
{
   int argc = GetArgumentCount();
   char ** argv = GetArguments();
   return 0;
}

编辑: 在win32中可以使用LPTSTR WINAPI GetCommandLine(void);

https://msdn.microsoft.com/en-us/library/ms683156(v=vs.85).aspx

我正在寻找 Linux 中的等效函数。

【问题讨论】:

  • 读取命令行时不必使用全局变量,这是程序架构的问题。
  • 您为什么要这样做?通过int main(int, char**) 获取它们有什么问题?你能给我们什么充分的理由不从传递给main的参数中检索它们吗?
  • 非常不清楚的问题,因为它缺乏动力。
  • 为什么全局函数是完美的而变量不是?正如其他人所说,这种设计似乎很糟糕。
  • @grimgrom:请编辑您的问题以改进它并添加动机和背景。一般来说,你所要求的都是疯狂的。

标签: c++


【解决方案1】:

是否可以在不接收的情况下获取命令行参数 他们通过int main(int, char**)?

是的,具有特定于平台的功能。但这不是必需的(见下文)。

我不想将参数传递给多个方法,

这是可以理解的。这是一种反模式,也称为“tramp data”。

另外,我不想通过全局变量自己存储参数。

是的,全局变量很少是个好主意。

这是另一种方法:将它们作为 static 本地容器对象存储在一些全局可用的非成员函数中,该函数通过引用返回容器。

例子:

#include <iostream>
#include <string>
#include <vector>

std::vector<std::string>& Arguments()
{
    static std::vector<std::string> arguments;
    return arguments;
}

void f()
{
    // use arguments anywhere else:
    std::cout << Arguments()[0];
}

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; ++i)
    {
        Arguments().push_back(argv[i]);
    }

    f();
}

当然,这可以做得更复杂。例如,您可能希望通过将向量包装在一个类中并将main 声明为friend 来防止除main 之外的任何其他人更改向量,如下所示:

#include <iostream>
#include <string>
#include <vector>

class Arguments final
{
public:
    static int Count()
    {
        return arguments.size();
    }

    static std::string Get(int index)
    {
        return arguments[index];
    };

private:
    Arguments() = delete;
    friend int main(int argc, char* argv[]);
    static std::vector<std::string> arguments;
};

std::vector<std::string> Arguments::arguments;

void f()
{
    // use Arguments anywhere else:
    std::cout << Arguments::Get(0);
}

int main(int argc, char* argv[])
{
    for (int i = 0; i < argc; ++i)
    {
        Arguments::arguments.push_back(argv[i]);
    }

    f();
}

请注意,当静态对象被销毁时,需要特别注意避免程序关闭时出现错误。您必须确保没有静态对象的析构函数访问Arguments,否则您将面临未定义行为的风险。

【讨论】:

  • 遗憾的是,C++ 在 2017 年似乎并没有立即明显地处理这个问题。我的意思是,每个示例似乎都是原始的,并且重新发明了原始轮子;特别是来自 python 的地方,getarg 非常简单和好。
【解决方案2】:

是否可以在不通过 int main(int, char**) 接收的情况下获取命令行参数?

否(至少,不是以可移植方式),但是您可以将通常的 argcargv 放入一些 全局 变量(或其他全局数据,通常在解析之后)。这也可能包含在一些static 数据中,same translation unit 中的其他函数正在检索它。因此,一种合理(可读且可移植)的方法是:

static int myargc;
static char **myargv;
int GetArgumentCount(void) {
  return myargc;
}
char**GetArguments(void) {
  return myargv;
}
int main(int argc, char**argv) {
   myargc= argc;
   myargv= argv;
   /// etc....

请注意,在某些系统或某些实现中,您可能会以其他方式访问命令行参数。

肮脏的Linux特定技巧

例如,在 Linux 上,使用 proc(5),您可能会解析 /proc/self/cmdline,但这样做是不合理的(在您的 Linux 系统上,尝试在终端中运行 od -cx /proc/self/cmdline 来猜我的意思),所以我仍然建议使用int main(int argc, char**argv) 并在一些全局或静态数据中存储argcargv,或者更可能的是,做一些parsing of program arguments

因此,在 Linux 上,您可以编写 GetArgumentCountGetArguments 函数(通过解析 /proc/self/cmdline,另请参阅 this),但 这样做会很愚蠢 不使用 @来自main 的987654341@ 和argv(即使它在技术上是可行的)。编写如此疯狂的 GetArgumentCountGetArguments 来解析 /proc/self/cmdline 留给受虐狂读者作为练习。

也许你需要它,因为一些静态数据的构造函数 -running before main 并在它之前从 crt0 调用 - 使用它们;但在这种情况下,您的程序设计恕我直言非常错误。我不知道在 Windows 中是否可以使用类似的肮脏技巧。

【讨论】:

  • “另外,我不想通过全局变量自己存储参数。”
  • 从技术上讲,声称这完全不可能是错误的。收集 argc/argv 可能更便携,但如果ps(或任务管理器或一些等效的操作系统)可以向您显示您的命令行参数,那么您肯定可以以相同的方式获得它们@ 987654349@(或任务管理器或等效的操作系统)可以。
  • @HWalters;感谢您的评论,这启发了我一个更好的答案。但我上面的回答和this 一样邪恶(被否决了)。
  • 在 Windows 上,您可以使用 GetCommandLineW()CommandLineToArgvW()
【解决方案3】:

如果您真的认为这是个好主意,您可以轻松地将 cor 命令行参数设为全局:

int argc_ = 0;
char** argv_ = NULL;

int main(int argc, char* argv[]) {
    argc_ = argc;
    argv_ = argv;

    // ...
}

【讨论】:

    猜你喜欢
    • 2011-03-21
    • 2011-07-06
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 2023-03-11
    • 1970-01-01
    • 2015-01-17
    相关资源
    最近更新 更多