在 main() 之外处理 argc 和 argv

Posted

技术标签:

【中文标题】在 main() 之外处理 argc 和 argv【英文标题】:Process argc and argv outside of main() 【发布时间】:2012-10-03 11:44:38 【问题描述】:

如果我想将用于处理命令行参数的大部分代码保留在 main 之外(用于组织和更易读的代码),最好的方法是什么?

void main(int argc, char* argv[])
    //lots of code here I would like to move elsewhere

【问题讨论】:

【参考方案1】:

只要可行,就应该遵守标准。因此,不要写

void main

它从来不是有效的 C 或 C++,而是写成

int main

这样,您的代码就可以编译,例如g++(使用常用的编译器选项)。

鉴于void main 我怀疑是Windows 环境。而且无论如何,为了支持在 Windows 环境中使用您的程序,您不应该在 Windows 中使用 main 参数。它们在 *nix 中工作,因为它们是在那个环境中设计的;它们通常不能在 Windows 中工作,因为默认情况下(按照非常严格的约定)它们被编码为 Windows ANSI,这意味着它们不能使用用户当前语言环境之外的字符对文件名进行编码。

因此,对于 Windows,您最好使用 GetCommandLine API 函数及其姊妹解析函数。为了可移植性,这应该更好地封装在一些命令行参数模块中。然后你需要处理在 Windows 中使用 wchar_t 和在 *nix 中使用 char 的有趣问题......

无论如何,我不确定对应的*nix API,或者即使有,但谷歌它。在最坏的情况下,对于 *nix,您始终可以从 main 初始化命令行参数模块。 *nix 的丑陋直接源于需要使用 C++ 最不可移植的、特定于操作系统的构造(即标准 main)支持可移植性。

【讨论】:

我完全同意int main 而不是void main。然而,其他评论让我……困惑。除了 Windows 之外,哪个系统对main() 的标准 C++ 约定有问题?我不知道,因此将标准约定斥为“不可移植”和“特定于操作系统”似乎是 OTT。 @JonathanLeffler:我不知道除 Windows 之外的任何常用系统,其中 main 参数不起作用(英文字母纯 ASCII 文本除外)。尽管如此,在 Windows 中不起作用的功能不可移植的,而专为 Unix 领域设计的功能特定于操作系统的。并且main 参数约定在 Windows 中都不起作用(即不可移植),并且是为 Unix-land 设计的(即是特定于操作系统的),并且这两个方面密切相关。绝对没有什么好笑的。我只能想到它持续存在的丑陋的政治原因。【参考方案2】:

Linux 提供program_invocation_nameprogram_invocation_name_short

【讨论】:

【参考方案3】:

查看“getoptlong”系列函数和库。这些提供了一种结构化的方式来定义您的程序期望的参数,然后可以轻松地为您解析它们。还可以帮助生成文档/帮助响应。

它是 UNIX 世界中的一个旧库,在 C# 中也有一个 .Net 实现。 (+ Perl、Ruby,可能还有更多。很高兴有一个可用于所有这些的单一范例!一次学习,随处使用!)

【讨论】:

【参考方案4】:

要么将它们作为参数传递,要么将它们存储在全局变量中。只要您不从 main 返回并尝试在 atexit 处理程序或全局范围内的对象的析构函数中处理它们,它们仍然存在并且可以从任何范围访问。

例如:

// Passing them as args:
void process_command_line(int argc, char **argv)

    // Use argc and argv
    ...


int main(int argc, char **argv)

    process_command_line(argc, argv);
    ...

或者:

// Global variables
int g_argc;
char **g_argv;

void process_command_line()

    // Use g_argc and g_argv
    ...


int main(int argc, char **argv)

    g_argc = argc;
    g_argv = argv;
    process_command_line();
    ...

将它们作为参数传递是一种更好的设计,因为它是经过封装的,让您可以根据需要修改/替换参数,或者轻松地将程序转换为库。全局变量更容易,因为如果您有许多不同的函数出于任何原因访问 args,您只需将它们存储一次,而无需在所有不同的函数之间不断传递它们。

【讨论】:

【参考方案5】:

只需将argcargv 作为要处理它们的函数的参数传递。

void parse_arg(int argc, char *argv[]);

【讨论】:

以上是关于在 main() 之外处理 argc 和 argv的主要内容,如果未能解决你的问题,请参考以下文章

int main(int argc, char * argv[]) 里的异常处理

int main(int argc, char* argv[]) 和 int main(int argc, char** argv) [关闭]

main (int argc,char *argv[]) 或main (int argc,char **argv)区别

argc 和 argv 用于除 main 以外的函数

main中的argv和argc

C++ main函数中参数argc和argv含义及用法