≡ Menu

C argc and argv Examples to Parse Command Line Arguments

Whenever you execute a program on a terminal, you can pass some arguments that are expected by the program, which can be used during the execution of the program. Here, system provides internal facility to maintain all arguments passed from user while executing program. These arguments are known as “Command line arguments”.

In this tutorial, we will map the understanding of command line arguments with working program to understand it better in crisp and clear way. But before jumping to program, we should know how system provides facility of command line arguments. As we know, Every C program must have main() function and the facility of command line arguments is provided by the main() function itself. When given below declaration is used in program, and then program has facility to use/manipulate command line arguments.

int main (int argc, char *argv[])

Here, argc parameter is the count of total command line arguments passed to executable on execution (including name of executable as first argument). argv parameter is the array of character string of each command line argument passed to executable on execution. If you are new to C programming, you should first understand how C array works.

Given below is the working program using command line argument.

 #include <stdio.h>

 int main (int argc, char *argv[]) {
 int i=0;
 printf("\ncmdline args count=%s", argc);

 /* First argument is executable name only */
 printf("\nexe name=%s", argv[0]);

 for (i=1; i< argc; i++) {
     printf("\narg%d=%s", i, argv[i]);
 }

 printf("\n");
 return 0;
 }

Given below is output when program is executed.

$ ./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

In above output, we can see total arguments count is internally maintained by “argc” parameter of main() which holds value ‘7’ (in which one argument is executable name and ‘6’ are arguments passed to program).And, all argument values are stored in “argv” parameter of main() which is array of character strings. Here, main () function stores each argument value as character string. We can see, iterating over “argv” array, we can get all passed arguments in the program.

There is one more declaration of main () function that provides added facility to work on environment variables inside program. Like, arguments maintained in argv[] array, main() function has internal facility to maintain all system environment variables into array of character strings which can be taken as an main() function parameter. Given below is the declaration.

int main (int argc, char *argv[], char **envp)

Given below is the working program using command line argument along with environment variables.

#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 only */
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;
}

Output of above program is given below.

$ ./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=https://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
$

In above output, we can see all system environment variables can be obtained third parameter of main() function which are traversed in program and displayed in output.

Passing command line arguments to program and manipulate arguments

Given below is program working on command line arguments.

#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 only */
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 on failure */
if ( file == NULL) {
    printf("\nCould not open file");
  }
else {
    printf("\nFile (%s) opened", argv[3]);
    /* Closing file */
    fclose(file);
  }

printf("\n");
return 0;
}

Output of above program is given below.

 $ ./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

In above output, we can see that command line arguments can be manipulated in program; all arguments are obtained as character string which can be converted into integer, float, long as shown in program. Even any character string if passed as an path of any file that can be used by program to file handling operation oh that file. We can see in above program, (/home/sitaram/test_progs/cmdline/cmdline_strfunc.c ) file path is passed as an command line argument which is used inside program to open the file and close the file.

Getopt() API

If we explore more on command line arguments, we have very powerful API – getopt(). It facilitates programmer to parse command line options. Programmer can give list of mandatory or optional command line options to getopt(). It can determine whether command line option is either valid or invalid as per program expected command line options. There are few getopt() specific internal variables like “optarg, optopt, opterr”

  • Optarg: contains pointer to command line valid option’s argument
  • Optopt: contains command line option if mandatory command line option is missing
  • Opterr: set to non-zero when invalid option is provided or value of mandatory command line option is not given

Given below is basic program to understand parsing of command line options.

 

#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;
 }

Output of above program is given below with few combinations of command line options:

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

In above program, ‘i’ and ‘o’ are taken as mandatory input and output command line options for program using getopt() API.

We would now have basic explanation of each case executed in above program:

  • In Case1, both mandatory command line options with their arguments are provided which are properly handled in first two cases of switch condition of program.
  • In Case2, value of mandatory input option is not given but we can see getopt() is not intelligent enough and considered “-o” as value of ‘I’ command line option. It is not error case for getopt(), but programmer can itself add intelligence to handle such case.
  • In Case3, only command line option is specified without its value and this is mandatory option so in this case getopt() would return ‘?’ and “optopt” variable is set to ‘i’ to confirm mandatory input option’s value is missing.
  • In Case4, mandatory output option’s value is missing.
  • In Case5, invalid command line option is given which is not mandatory or optional command line option. In this case, getopt() returned ‘?’ and optopt is not set since it is unknown character not expected by getopt().
Add your comment

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

Comments on this entry are closed.

  • Jalal Hajigholamali January 31, 2013, 4:59 am

    Hi,

    Thanks a lot for very nice and useful article

  • DuskoKoscica February 8, 2013, 4:36 am

    Haven’t use those things lately,,,,

    It is bit old for me, but it is good to know…..

    Well, I try to think like list of pointers, sometimes I think of those things like switch board that have wires that can be moved to another board.

    Something like that….

  • Siva Krishna February 24, 2013, 4:15 am

    Thank you very much. I usually feel difficult to understand the getopt () function call. Now, its clear for me.

  • karl S-P March 18, 2013, 12:36 pm

    Being from the old school of C programming I always just ground out the options from analyzing argv. Never thought to use getopt and never learned how to use it. This is great information to have. Wish I had learned it long ago.

  • court April 23, 2014, 7:17 pm

    Line 5 of cmdline_basic has the %s specifier expecting a char * and recieving an int. Its going to write to memory that doesn’t belong to it. Good article though.

  • Sepahrad Salour October 3, 2015, 2:41 am

    Thanks for your helpful article….

  • Alex February 18, 2016, 2:08 am

    Thank you very much for your post.
    It is really well made.

  • lDarkllArg March 20, 2016, 9:54 am

    this is just what I was looking for! Thank you very much!

  • Tom June 22, 2016, 7:03 pm

    Thanks for the tutorial.
    Heads up, your first example crashes because of a %s in the printf trying to print argc.

  • Paul March 12, 2017, 1:46 pm

    Great article, it helped me a lot.

    Thanks