无论何时在终端上执行程序,都可以传递程序期望的一些参数,这些参数可以在程序执行期间使用。在这里,系统提供了内部工具来维护在执行程序时从用户传递的所有参数。这些参数称为“命令行参数”。
在本教程中,我们将对命令行参数的理解与工作程序相映射,以清晰明了的方式更好地理解命令行参数。但是在跳转到程序之前,我们应该知道系统如何提供命令行参数的工具。众所周知,每个C程序都必须具有main()函数,而命令行参数的功能则由main()函数本身提供。当在下面给出声明时,在程序中使用了声明,然后程序具有使用/操纵命令行参数的便利。
int main (int argc, char *argv[])
在这里,argc参数是在执行时传递给可执行文件的命令行参数总数(包括可执行文件的名称作为第一个参数)。 argv参数是在执行时传递给可执行文件的每个命令行参数的字符串数组。如果您不熟悉C编程,则应首先了解如何 C数组 作品。
下面给出的是使用命令行参数的工作程序。
#include <stdio.h> int main (int argc, char *argv[]) { int i=0; printf("\ncmdline args count=%s", argc); /* First argument is executable name 上 ly */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } printf("\n"); return 0; }
下面给出的是程序执行时的输出。
$ ./cmdline_basic test1 test2 test3 test4 1234 56789 cmdline args count=7 exe name=./cmdline_basic arg1=test1 arg2=test2 arg3=test3 arg4=test4 arg5=1234 arg6=56789
在上面的输出中,我们可以看到参数总数由main()的“ argc”参数在内部维护,该参数包含值“ 7”(其中一个参数是可执行文件名称,而“ 6”是传递给程序的参数)。参数值存储在main()的“ argv”参数中,该参数是字符串数组。在这里,main()函数将每个参数值存储为字符串。我们可以看到,遍历“ argv”数组,我们可以获取程序中所有传递的参数。
main()函数还有一个声明,它提供了在程序内部处理环境变量的附加功能。像在argv []数组中维护的参数一样,main()函数具有内部功能,可以将所有系统环境变量维护为字符串数组,可以将其用作main()函数参数。以下是声明。
int main (int argc, char *argv[], char **envp)
下面给出的是使用命令行参数和环境变量的工作程序。
#include <stdio.h> int main (int argc, char *argv[], char **env_var_ptr) { int i=0; printf("\ncmdline args count=%d", argc); /* First argument is executable name 上 ly */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } i=0; while (*env_var_ptr != NULL) { i++; printf ("\nenv var%d=>%s",i, *(env_var_ptr++)); } printf("\n"); return 0; }
上面程序的输出如下。
$ ./env test1 test2 cmdline args count=3 exe name=./env arg1=test1 arg2=test2 env var1=>SSH_AGENT_PID=1575 env var2=>KDE_MULTIHEAD=false env var3=>SHELL=/bin/bash env var4=>TERM=xterm env var5=>XDG_SESSION_COOKIE=5edf27907e97deafc70d310550995c84-1352614770.691861-1384749481 env var6=>GTK2_RC_FILES=/etc/gtk-2.0/gtkrc:/home/sitaram/.gtkrc-2.0:/home/sitaram/.kde/share/config/gtkrc-2.0 env var7=>KONSOLE_DBUS_SERVICE=:1.76 env var8=>KONSOLE_PROFILE_NAME=Shell env var9=>GS_LIB=/home/sitaram/.fonts env var10=>GTK_RC_FILES=/etc/gtk/gtkrc:/home/sitaram/.gtkrc:/home/sitaram/.kde/share/config/gtkrc env var11=>WINDOWID=29360154 env var12=>GNOME_KEYRING_CONTROL=/run/user/sitaram/keyring-2Qx7DW env var13=>SHELL_SESSION_ID=f7ac2d9459c74000b6fd9b2df1d48da4 env var14=>GTK_MODULES=overlay-scrollbar env var15=>KDE_FULL_SESSION=true env var16=>http_proxy=http://10.0.0.17:8080/ env var17=>USER=sitaram env var18=>LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36: env var19=>XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0 env var20=>XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0 env var21=>SSH_AUTH_SOCK=/tmp/ssh-kIFY5HttOJxe/agent.1489 env var22=>ftp_proxy=ftp://10.0.0.17:8080/ env var23=>SESSION_MANAGER=local/Sitaram:@/tmp/.ICE-unix/1716,unix/Sitaram:/tmp/.ICE-unix/1716 env var24=>DEFAULTS_PATH=/usr/share/gconf/kde-plasma.default.path env var25=>XDG_CONFIG_DIRS=/etc/xdg/xdg-kde-plasma:/etc/xdg env var26=>DESKTOP_SESSION=kde-plasma env var27=>PATH=/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games env var28=>PWD=/home/sitaram/test_progs/cmdline env var29=>socks_proxy=socks://10.0.0.17:8080/ env var30=>KONSOLE_DBUS_WINDOW=/Windows/1 env var31=>KDE_SESSION_UID=1000 env var32=>LANG=en_IN env var33=>GNOME_KEYRING_PID=1478 env var34=>MANDATORY_PATH=/usr/share/gconf/kde-plasma.mandatory.path env var35=>UBUNTU_MENUPROXY=libappmenu.so env var36=>KONSOLE_DBUS_SESSION=/Sessions/1 env var37=>https_proxy=//10.0.0.17:8080/ env var38=>GDMSESSION=kde-plasma env var39=>SHLVL=1 env var40=>HOME=/home/sitaram env var41=>COLORFGBG=15;0 env var42=>KDE_SESSION_VERSION=4 env var43=>LANGUAGE=en_IN:en env var44=>XCURSOR_THEME=Oxygen_White env var45=>LOGNAME=sitaram env var46=>XDG_DATA_DIRS=/usr/share/kde-plasma:/usr/local/share/:/usr/share/ env var47=>DBUS_SESSION_BUS_ADDRESS=unix:abstract=/tmp/dbus-mnJhMvd4jG,guid=435ddd41500fd6c5550ed8d2509f4374 env var48=>LESSOPEN=| /usr/bin/lesspipe %s env var49=>PROFILEHOME= env var50=>XDG_RUNTIME_DIR=/run/user/sitaram env var51=>DISPLAY=:0 env var52=>QT_PLUGIN_PATH=/home/sitaram/.kde/lib/kde4/plugins/:/usr/lib/kde4/plugins/ env var53=>LESSCLOSE=/usr/bin/lesspipe %s %s env var54=>XAUTHORITY=/tmp/kde-sitaram/xauth-1000-_0 env var55=>_=./env env var56=>OLDPWD=/home/sitaram/test_progs $
在上面的输出中,我们可以看到可以从main()函数的第三个参数获得所有系统环境变量,这些参数在程序中遍历并在输出中显示。
将命令行参数传递给编程和操纵参数
下面给出的是处理命令行参数的程序。
#include <stdio.h> #include <stdlib.h> int main (int argc, char *argv[]) { int i=0; int d; float f; long int l; FILE *file = NULL; printf("\ncmdline args count=%d", argc); /* First argument is executable name 上 ly */ printf("\nexe name=%s", argv[0]); for (i=1; i< argc; i++) { printf("\narg%d=%s", i, argv[i]); } /* Conversion string into int */ d = atoi(argv[1]); printf("\nargv[1] in intger=%d",d); /* Conversion string into float */ f = atof(argv[1]); printf("\nargv[1] in float=%f",f); /* Conversion string into long int */ l = strtol(argv[2], NULL, 0); printf("\nargv[2] in long int=%ld",l); /*Open file whose path is passed as an argument */ file = fopen( argv[3], "r" ); /* fopen returns NULL pointer 上 failure */ if ( file == NULL) { printf("\nCould not open file"); } else { printf("\nFile (%s) opened", argv[3]); /* Closing file */ fclose(file); } printf("\n"); return 0; }
上面程序的输出如下。
$ ./cmdline_strfunc 1234test 12345678 /home/sitaram/test_progs/cmdline/cmdline_strfunc.c cmdline args count=4 exe name=./cmdline_strfunc arg1=1234test arg2=12345678 arg3=/home/sitaram/test_progs/cmdline/cmdline_strfunc.c argv[1] in intger=1234 argv[1] in float=1234.000000 argv[2] in long int=12345678 File (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c) opened
在上面的输出中,我们可以看到可以在程序中操作命令行参数。所有参数都以字符串形式获取,可以将其转换为整数,浮点数,如程序所示。即使是任何字符串,如果作为任何文件的路径传递,程序也可以使用它来对该文件进行文件处理操作。我们可以在上面的程序中看到(/home/sitaram/test_progs/cmdline/cmdline_strfunc.c)文件路径作为命令行参数传递,该路径在程序内部用于打开文件和关闭文件。
Getopt()API
如果我们在命令行参数上进行更多研究,我们将拥有非常强大的API – getopt()。它有助于程序员解析命令行选项。程序员可以将强制或可选命令行选项列表提供给getopt()。它可以根据程序预期的命令行选项确定命令行选项是有效还是无效。几乎没有特定于getopt()的内部变量,例如“ optarg,optopt,opterr”
- Optarg:包含指向命令行有效选项参数的指针
- Optopt:如果缺少必需的命令行选项,则包含命令行选项
- Opterr:在提供无效选项或未提供强制命令行选项的值时设置为非零
下面给出的是基本程序,用于了解命令行选项的解析。
#include <stdio.h> #include <unistd.h> int main (int argc, char *argv[]) { int opt = 0; char *in_fname = NULL; char *out_fname = NULL; while ((opt = getopt(argc, argv, "i:o:")) != -1) { switch(opt) { case 'i': in_fname = optarg; printf("\nInput option value=%s", in_fname); break; case 'o': out_fname = optarg; printf("\nOutput option value=%s", out_fname); break; case '?': /* Case when user enters the command as * $ ./cmd_exe -i */ if (optopt == 'i') { printf("\nMissing mandatory input option"); /* Case when user enters the command as * # ./cmd_exe -o */ } else if (optopt == 'o') { printf("\nMissing mandatory output option"); } else { printf("\nInvalid option received"); } break; } } printf("\n"); return 0; }
下面是上述程序的输出,其中包含一些命令行选项组合:
Case1: $ ./cmdline_getopt -i /tmp/input -o /tmp/output Input option value=/tmp/input Output option value=/tmp/output Case2: $ ./cmdline_getopt -i -o /tmp/output Input option value=-o Case3: $ ./cmdline_getopt -i ./cmdline_getopt: option requires an argument -- 'i' Missing mandatory input option Case4: $ ./cmdline_getopt -i /tmp/input -o ./cmdline_getopt: option requires an argument -- 'o' Input option value=/tmp/input Missing mandatory output option Case5: $ ./cmdline_getopt -k /tmp/input ./cmdline_getopt: invalid option -- 'k' Invalid option received
在上述程序中,“ i”和“ o”被用作使用getopt()API的程序的强制输入和输出命令行选项。
现在,我们将对上述程序中执行的每种情况有基本的解释:
- 在Case1中,提供了两个强制性命令行选项及其参数,在程序的切换条件的前两种情况下可以正确处理。
- 在Case2中,未提供强制输入选项的值,但我们可以看到getopt()不够智能,因此将“ -o”视为“ I”命令行选项的值。对于getopt()来说,这不是错误的情况,但是程序员本身可以添加智能来处理这种情况。
- 在Case3中,仅指定了命令行选项而没有其值,这是必选选项,因此在这种情况下,getopt()将返回“?”,并且将“ optopt”变量设置为“ i”以确认缺少必选输入选项的值。
- 在Case4中,缺少强制输出选项的值。
- 在Case5中,给出了无效的命令行选项,该选项不是必需的或可选的命令行选项。在这种情况下,getopt()返回了“?”,并且未设置optopt,因为它是getopt()不需要的未知字符。
如果您喜欢这篇文章,您可能还会喜欢..
![]() |
![]() |
![]() |
![]() |
你好
非常感谢您写的非常好和有用的文章