Gre*_*ven 476 c++ parameters argv command-line-arguments argc
在许多C++ IDE和编译器中,当它为您生成主函数时,它看起来像这样:
int main(int argc, char *argv[])
Run Code Online (Sandbox Code Playgroud)
当我在没有IDE的情况下编写C++代码时,只需使用命令行编译器,我输入:
int main()
Run Code Online (Sandbox Code Playgroud)
没有任何参数.这意味着什么,对我的计划至关重要?
mea*_*gar 615
argv
以及argc
如何main()
在C和C++ 中传递命令行参数.
argc
将是指向的字符串数argv
.这将(实际上)为1加上参数的数量,因为几乎所有实现都会将程序的名称添加到数组中.
变量按约定命名argc
(参数计数)和argv
(参数矢量),但它们可以被赋予任何有效的标识符:int main(int num_args, char** arg_strings)
同样有效.
int main()
如果您不打算处理命令行参数,它们也可以完全省略,产生.
尝试以下程序:
#include <iostream>
int main(int argc, char** argv) {
std::cout << "Have " << argc << " arguments:" << std::endl;
for (int i = 0; i < argc; ++i) {
std::cout << argv[i] << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
运行它将./test a1 b2 c3
输出
Have 4 arguments:
./test
a1
b2
c3
Run Code Online (Sandbox Code Playgroud)
Joh*_*ker 50
argc
是从命令行传递到程序中的参数数量,是参数argv
数组.
你可以通过参数循环知道它们的数量,如:
for(int i = 0; i < argc; i++)
{
// argv[i] is the argument at index i
}
Run Code Online (Sandbox Code Playgroud)
Tob*_*ght 18
假设您运行程序(使用sh
语法):
myprog arg1 arg2 'arg 3'
Run Code Online (Sandbox Code Playgroud)
如果您将main声明为int main(int argc, char *argv[])
,那么(在大多数环境中),您main()
将被调用,如同:
p = { "myprog", "arg1", "arg2", "arg 3", NULL };
exit(main(4, p));
Run Code Online (Sandbox Code Playgroud)
但是,如果你将main声明为int main()
,它将被称为类似的东西
exit(main());
Run Code Online (Sandbox Code Playgroud)
并且你没有得到传递的参数.
还有两点需要注意:
main
.如果特定平台接受额外的参数或不同的返回类型,那么这是一个扩展,不应该依赖于可移植程序.*argv[]
并且**argv
完全等价,所以你可以写int main(int argc, char *argv[])
为int main(int argc, char **argv)
.use*_*570 14
让我们考虑一下声明:
int main (int argc, char *argv[])
Run Code Online (Sandbox Code Playgroud)
在上面的声明中,第二个参数named的类型argv
实际上是a char**
。也就是说,argv
是一个指向 a 的指针char
。这是因为 a由于类型衰减而char* []
衰减为 a 。例如,下面给出的声明是等效的:char**
int main (int argc, char *argv[]); //first declaration
int main (int argc, char **argv); //RE-DECLARATION. Equivalent to the above declaration
Run Code Online (Sandbox Code Playgroud)
换句话说,argv
是一个指针,指向元素类型为 的数组的第一个元素char*
。此外,argv[i]
数组的每个元素(具有类型的元素)本身都指向一个字符,该字符是空终止字符串char*
的开头。也就是说,每个元素都指向具有类型(而不是)元素的数组的第一个元素。给出一个图表以供说明:argv[i]
char
const char
main
正如其他答案中已经说过的,当我们想要使用命令行参数时,使用这种形式的声明。
用于main
表示程序启动时提供给程序的命令行参数的参数.该argc
参数表示命令行参数的数量,并且char *argv[]
是一个字符串数组(字符指针),表示命令行上提供的各个参数.
小智 5
该main
函数可以有两个参数,argc
和argv
.argc
是一个integer(int
)参数,它是传递给程序的参数数量.
程序名始终是第一个参数,因此程序中至少有一个参数,最小值argc
为1.但是如果一个程序本身有两个参数,那么它的值argc
将是三.
参数argv
指向字符串数组,称为参数向量.它是函数参数的一维字符串数组.
int main();
Run Code Online (Sandbox Code Playgroud)
这是一个简单的声明。它不能接受任何命令行参数。
int main(int argc, char* argv[]);
Run Code Online (Sandbox Code Playgroud)
当您的程序必须接受命令行参数时,将使用此声明。当这样运行时:
myprogram arg1 arg2 arg3
Run Code Online (Sandbox Code Playgroud)
argc
或参数计数设置为4(四个参数),而argv
参数或参数向量将填充指向“ myprogram”,“ arg1”,“ arg2”和“ arg3”的字符串指针。程序调用(myprogram
)包含在参数中!
或者,您可以使用:
int main(int argc, char** argv);
Run Code Online (Sandbox Code Playgroud)
这也是有效的。
您可以添加另一个参数:
int main (int argc, char *argv[], char *envp[])
Run Code Online (Sandbox Code Playgroud)
该envp
参数还包含环境变量。每个条目都遵循以下格式:
VARIABLENAME=VariableValue
Run Code Online (Sandbox Code Playgroud)
像这样:
SHELL=/bin/bash
Run Code Online (Sandbox Code Playgroud)
环境变量列表以空值结尾。
重要提示:请勿在对!的调用中直接使用argv
或envp
值system()
。这是一个巨大的安全漏洞,因为恶意用户可以将环境变量设置为命令行命令,并(可能)造成巨大破坏。通常,不要使用system()
。通过C库几乎总是存在更好的解决方案。
命令行参数: main( int argc, char * argv[] )
\n在 Unix 中,当您将附加参数传递给命令时,这些命令必须传递给执行进程。例如,在调用 中ls -al
,它执行程序ls
并将字符串-al
作为参数传递:
% ls\ncontent.html index.html primary.0.html\n% ls -al\ntotal 20\ndrwxr-xr-x 2 dwharder users 4096 Sep 11 16:38 .\ndrwxr-xr-x 6 dwharder users 4096 Sep 11 16:35 ..\n-rwxr-xr-x 1 dwharder users 117 Sep 11 16:38 content.html\n-rwxr-xr-x 1 dwharder users 1400 Sep 11 16:37 index.html\n-rwxr-xr-x 1 dwharder users 532 Sep 11 16:38 primary.0.html\n%\n
Run Code Online (Sandbox Code Playgroud)\n正在运行的程序访问这些附加参数的方式是将它们作为参数传递给函数 main:
\nint main( int argc, char *argv[] ) {\n
Run Code Online (Sandbox Code Playgroud)\n这里的argc
意思是参数计数,argv
意思是参数向量。
第一个参数是传递的参数数量加上一个,以包含为使这些进程运行而执行的程序的名称。因此,argc
始终大于零,并且argv[0]
是为开始此过程而运行的可执行文件的名称(包括路径)。例如,如果我们运行
#include <stdio.h>\n\nint main( int argc, char *argv[] ) {\n printf( "argv[0]: %s\\n", argv[0] );\n\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n在这里,我们编译此代码并首先编译并运行它,以便可执行文件名称为a.out
,然后我们再次编译并运行它,以便可执行文件名称为arg
:
% gcc argument.0.c\n% ./a.out \nargv[0]: ./a.out\n% gcc -o arg argument.0.c\n% ./arg \nargv[0]: ./arg\n%\n
Run Code Online (Sandbox Code Playgroud)\n如果传递更多额外的命令行参数,则所有字符的字符串将根据一些规则被解析并分成子字符串;但是,如果所有字符都是字符、数字或空格,则 shell 会根据空格分隔这些字符,并分配args[1]
第一个字符的地址、args[2]
第二个字符的地址,依此类推。
以下程序打印所有参数:
\n#include <stdio.h>\n\nint main( int argc, char *argv[] ) {\n int i;\n\n printf( "argc: %d\\n", argc );\n printf( "argv[0]: %s\\n", argv[0] );\n\n if ( argc == 1 ) {\n printf( "No arguments were passed.\\n" );\n } else {\n printf( "Arguments:\\n" );\n\n for ( i = 1; i < argc; ++i ) {\n printf( " %d. %s\\n", i, argv[i] );\n }\n }\n\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n在这里,我们使用 1 个然后 12 个命令行参数执行该程序:
\n% gcc argument.c\n% ./a.out first\nargc: 2\nargv[0]: ./a.out\nArguments:\n 1. first\n% ./a.out first second third fourth fifth sixth seventh eighth ninth tenth eleventh twelfth\nargc: 13\nargv[0]: ./a.out\nArguments:\n 1. first\n 2. second\n 3. third\n 4. fourth\n 5. fifth\n 6. sixth\n 7. seventh\n 8. eighth\n 9. ninth\n 10. tenth\n 11. eleventh\n 12. twelfth\n% \n
Run Code Online (Sandbox Code Playgroud)\n为了娱乐
\n现在,您可能想知道实际发生了什么(如果您不知道,欢迎您跳过这一点)。首先,当执行命令时,shell 解析命令行并用空字符分隔各个部分\\0
。例如,执行
% ./a.out first second third fourth fifth\n
Run Code Online (Sandbox Code Playgroud)\n让 shell 生成字符串./a.out\xe2\x98\x90first\xe2\x98\x90second\xe2\x98\x90third\xe2\x98\x90fourth\xe2\x98\x90fifth\xe2\x98\x90
,其中框代表空字符。接下来,为六个 ( argc
) 指针的数组分配内存,并将这六个指针分配给命令行解析到的每个字符串的第一个字符。最后,为堆栈分配内存,并使用 8 字节对齐,将两个参数放入堆栈中。如图 1 所示。
./a.out first second third fourth fifth
图 1.命令行调用的结果。
进一步的乐趣
\n在 Unix 中,shell 对命令进行进一步处理。例如,如果它发现指示当前目录中的文件的通配符,它将尝试扩展这些通配符。其中包括?
一个未知字符和*
任意数量的字符。
例如,以下命令检查当前目录中的文件:
\n% ls\na.out argument.0.c argument.1.c content.html images index.html primary.0.html src\n% ./a.out *\nargc: 9\nargv[0]: ./a.out\nArguments:\n 1. a.out\n 2. argument.0.c\n 3. argument.1.c\n 4. content.html\n 5. images\n 6. index.html\n 7. primary.0.html\n 8. src\n% ./a.out *.html\nargc: 4\nargv[0]: ./a.out\nArguments:\n 1. content.html\n 2. index.html\n 3. primary.0.html\n% ./a.out argument.?.c\nargc: 3\nargv[0]: ./a.out\nArguments:\n 1. argument.0.c\n 2. argument.1.c\n
Run Code Online (Sandbox Code Playgroud)\n同样,您可以告诉命令行将空格视为一个字符串的一部分,或者通过在空格或通配符之前使用反斜杠或用单引号或双引号将字符串括起来来忽略通配符。
\n% ./a.out hi\\ there\\?\nargc: 2\nargv[0]: ./a.out\nArguments:\n 1. hi there?\n% ./a.out "hi there?"\nargc: 2\nargv[0]: ./a.out\nArguments:\n 1. hi there?\n% ./a.out \'hi there?\'\nargc: 2\nargv[0]: ./a.out\nArguments:\n 1. hi there?\n%\n
Run Code Online (Sandbox Code Playgroud)\n最后,如果您用反引号包围文本,它将首先执行该文本,然后将其替换为命令的输出:
\n% ./a.out `ls *.c`\nargc: 4\nargv[0]: ./a.out\nArguments:\n 2. argument.0.c\n 3. argument.1.c\n%\n
Run Code Online (Sandbox Code Playgroud)\n\n免责声明:以上帖子直接取自https://ece.uwaterloo.ca/~dwharder/icsrts/C/05/。它最初是由滑铁卢大学的道格拉斯·威廉·哈德 (Douglas Wilhelm Harder)编写的。如果它完全属于另一个人,那我为什么要把它放在这里?因为我读了他的文章,学到了新东西,我非常喜欢它,所以我把它放在这里,以便其他人也能从中受益。再说一次,所有的努力和掌声都属于哈德先生,而不是我。谢谢。
\n 归档时间: |
|
查看次数: |
813329 次 |
最近记录: |