在main()之外处理argc和argv的过程

10
如果我想让大部分处理命令行参数的代码保持在main函数之外(为了更好的组织和可读性),那么最好的方法是什么?
void main(int argc, char* argv[]){
    //lots of code here I would like to move elsewhere
}
5个回答

4

可以将它们作为参数传递,或者存储在全局变量中。只要你不从主函数返回并尝试在 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,您只需存储它们一次,而不需要在所有不同的函数之间不断传递它们。

4

在实际操作中,我们应该遵循标准。因此,请不要写:

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初始化一个命令行参数模块。与C++最不可移植的特定于操作系统的构造(即标准main)需要支持可移植性,这就是为*nix带来丑陋的原因。


我完全同意使用 int main 而不是 void main。然而,其他评论让我感到困惑。除了 Windows 以外的哪个系统存在与标准 C++ 的 main() 不兼容的问题呢?我不知道有这样的,因此批评将标准约定视为“非可移植”和“特定于操作系统”似乎过了头。 - Jonathan Leffler
@JonathanLeffler:除了 Windows 以外,我不知道还有哪个常用系统不能使用 main 参数(除了纯 ASCII 文本)。但是,一个在 Windows 上无法工作的特性不可移植的,而一个专为 Unix 设计的特性特定于操作系统的。而 main 参数约定既不能在 Windows 上工作(即不可移植),又是专为 Unix 设计的(即特定于操作系统),这两个方面是密切相关的。这一点绝对不好笑。我只能想到丑陋的政治原因来解释它的存在。 - Cheers and hth. - Alf

2

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

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


1

Linux提供program_invocation_nameprogram_invocation_name_short


0

看看 "getoptlong" 函数和库系列。它们提供了一种结构化的方式来定义程序所期望的参数,并且可以轻松地解析它们。还可以帮助生成文档/帮助响应。

这是 UNIX 世界中的一个古老库,也有 C# 的 .Net 实现。(还有 Perl、Ruby 等等。在所有这些语言中都能使用相同的范式!学一次,到处使用!)


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