- Pass arguments into C program from command line
- 6 Answers 6
- Program arguments in linux
- How To Pass and Parse Linux Bash Script Arguments and Parameters
- Passing arguments before running
- Detecting Command Line Arguments
- Assign Provided Arguments To Bash Variable
- Reading Multiple Arguments with For or While loop
- Reading With Parameter Names
- Using getopts to parse arguments and parameters
- Printing Values of All Arguments
- Accessing the number of Parameters passed
Pass arguments into C program from command line
So I’m in Linux and I want to have a program accept arguments when you execute it from the command line. For example, ./myprogram 42 -b -s So then the program would store that number 42 as an int and execute certain parts of code depending on what arguments it gets like -b or -s.
The canonical format for a command line passes option arguments such as ‘-b’ and ‘-s’ before any non-option arguments such as ’42’. So, the standard, orthodox command line format would be «./myprogram -b -s 42». Avoid deviating from that standard. [. more in next comment. ]
See section 12 (Utility conventions) of Base Definitions of the POSIX standard at opengroup.org/onlinepubs/009695399/toc.htm.
@Jonathan Leffler: The order doesn’t matter. getopt_long function does the right thing regardless of the order. See my answer.
6 Answers 6
#include #include #include #include int main (int argc, char **argv) < int bflag = 0; int sflag = 0; int index; int c; opterr = 0; while ((c = getopt (argc, argv, "bs")) != -1) switch (c) < case 'b': bflag = 1; break; case 's': sflag = 1; break; case '?': if (isprint (optopt)) fprintf (stderr, "Unknown option `-%c'.\n", optopt); else fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); return 1; default: abort (); >printf ("bflag = %d, sflag = %d\n", bflag, sflag); for (index = optind; index
It will work on Linux because the getopt() function is GNU getopt() and you don’t normally set POSIXLY_CORRECT in the environment, and GNU getopt() then processes option arguments before ‘file’ arguments, even when they follow a file argument as in the example. On POSIX platforms, it won’t work.
. because the 42 will stop the -b and -s options from being interpreted as options. Of course, the design of the command line is bad too. I’ll note that in the comments to the question.
@Jonathan: The question does have the tag linux . Therefore GNU getopt() example is appropriate here.
@J F Sebastian — yes, it does have a Linux tag; that’s why it has an upvote from me. The structure of a command line and arguments ordering should not rely on that quirk; well, I still have to work across other platforms, and GNU getopt is not standard on other platforms (for all it is available).
In C, this is done using arguments passed to your main() function:
int main(int argc, char *argv[]) < int i = 0; for (i = 0; i < argc; i++) < printf("argv[%d] = %s\n", i, argv[i]); >return 0; >
More information can be found online such as this Arguments to main article.
Sorry — that’s not a dreadfully good x-ref. There’s a bug in the statement that «The declaration of the argv argument is often a novice programmer’s first encounter with pointers to arrays of pointers and can prove intimidating» (argv is an array of pointers, not a pointer to an array of pointers).
Additionally, the next page shows an ad hoc option parser instead of using the standard getopt() or getopt_long() parsers — which is simply bad advice. No — it is not a good reference.
In C, a reference to an array is an address, just like a pointer is an address. Thus, argv can be referred to as both «an array» and «a pointer to an array». This is one of the beautiful simplicities of C as well as one of the points of confusions.
Consider using getopt_long() . It allows both short and long options in any combination.
#include #include #include /* Flag set by `--verbose'. */ static int verbose_flag; int main (int argc, char *argv[]) < while (1) < static struct option long_options[] = < /* This option set a flag. */ , /* These options don't set a flag. We distinguish them by their indices. */ , , >; /* getopt_long stores the option index here. */ int option_index = 0; int c = getopt_long (argc, argv, "bs", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) < case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; printf ("option %s", long_options[option_index].name); if (optarg) printf (" with arg %s", optarg); printf ("\n"); break; case 'b': puts ("option -b\n"); break; case 's': puts ("option -s\n"); break; case '?': /* getopt_long already printed an error message. */ break; default: abort (); >> if (verbose_flag) puts ("verbose flag is set"); /* Print any remaining command line arguments (not options). */ if (optind < argc) < printf ("non-option ARGV-elements: "); while (optind < argc) printf ("%s ", argv[optind++]); putchar ('\n'); >return 0; >
Program arguments in linux
The system starts a C program by calling the function main . It is up to you to write a function named main —otherwise, you won’t even be able to link your program without errors.
In ISO C you can define main either to take no arguments, or to take two arguments that represent the command line arguments to the program, like this:
int main (int argc, char *argv[])
The command line arguments are the whitespace-separated tokens given in the shell command used to invoke the program; thus, in ‘ cat foo bar ’, the arguments are ‘ foo ’ and ‘ bar ’. The only way a program can look at its command line arguments is via the arguments of main . If main doesn’t take arguments, then you cannot get at the command line.
The value of the argc argument is the number of command line arguments. The argv argument is a vector of C strings; its elements are the individual command line argument strings. The file name of the program being run is also included in the vector as the first element; the value of argc counts this element. A null pointer always follows the last element: argv [ argc ] is this null pointer.
For the command ‘ cat foo bar ’, argc is 3 and argv has three elements, «cat» , «foo» and «bar» .
In Unix systems you can define main a third way, using three arguments:
int main (int argc, char *argv[], char *envp[])
The first two arguments are just the same. The third argument envp gives the program’s environment; it is the same as the value of environ . See Environment Variables. POSIX.1 does not allow this three-argument form, so to be portable it is best to write main to take two arguments, and use the value of environ .
How To Pass and Parse Linux Bash Script Arguments and Parameters
Parsing and Passing of Arguments into bash scripts/ shell scripts is quite similar to the way in which we pass arguments to the functions inside Bash scripts. We’ll see the actual process of passing on the arguments to a script and also look at the way to access those arguments inside the script.
Passing arguments before running
We can pass parameters just after the name of the script while running the bash interpreter command. You can pass parameters or arguments to the file. Just the command for running the script normally by adding the value of the parameters directly to the script. Every parameter is a space-separated value to pass to the shell script.
The above command will just run the script without passing the parameters.
Whereas the command below will pass the arguments to the script.
bash scriptname.sh parameter1 parameter2 parameter3 nth-parameter
Running bash script with passing parameters
The above screenshot displays the parameters passed to the script, how we’ll do that, which we’ll explain in the next section. But right now we can see we have passed in the parameters from outside of the script using bash environment variables. You can even use strings and other data types but beware of any whitespace. White space will make the variable a separate parameter. So, for strings especially, be careful to strictly surround them with quotation marks.
Detecting Command Line Arguments
Now, we’ll see how we access those parameters inside of the script. We’ll use the number of the parameters passed in the order i.e for the first parameters passed, we’ll parse(access) the parameter by using $1 as the variable. The first parameter is stored in the $1 variable. Furthermore, you can assign this variable to any other user-defined variable you like. For the nth parameter passed, you can use $n to access that particular parameter. Here, the variable name starts with 1 because the filename/ script name is the 0th parameter. If you have more than 9 parameters, make sure to use < >around the number as without the parenthesis, bash will only see $10 as $1 and exclude the 0, so use $ and so on instead of simply $10.
#!/bin/bash echo "1st parameter = $1 " echo "2nd Parameter = $2 "
The above script can access the parameters from the command line/ shell using the positional parameters, which are 1, 2, 3, and so on.
Accessing the arguments from the script.
As you can see, we have used <> to access the parameter variable numbers from 10 onwards. The script can be used for loops and while loops to iterate over the parameters, but we will discuss it in further sections.
Assign Provided Arguments To Bash Variable
We can also assign it to other custom variables to make the script more dynamic and mold it according to the needs. Though the above script when run will only print two parameters, surely you can access more parameters using the variable as the order of parameters in numbers. The script can access the positional variables from the command line and use them in the required places wherever needed within the script.
#!/bin/bash a=$1 b=$2 p=$(($a*$b)) echo "The product of $a and $b = $p"
Assign Provided Arguments To Bash Variable
The above script accesses the positional parameters i.e $1 and $2 passed into the script and stores the user-defined variables to access them later and modify them accordingly. We can also access more parameters using iterative methods as we’ll see in the upcoming sections.
We also have the ability to check for any NULL or empty parameters passed using the -z or -n flags. From this, we can verify whether the parameters were passed or not.
#!/bin/bash if [[ -z $1 ]]; then echo "No parameter passed." else echo "Parameter passed = $1" fi
Checking for positional parameters passed in or not.
With this script, we can detect whether any positional parameters were passed in or nothing was passed. The -z flag checks for any NULL or uninitialized variables in BASH. The -z flag returns true if the variable passed is NULL or uninitialized. Hence, we can make use of basic If-else statements to detect the parameters passed.
We can also use -n flag which returns true if no parameters are passed, so we have to make use of ! to reverse the condition.
#!/bin/bash if [[ ! -n $1 ]]; then echo "No parameter passed." else echo "Parameter passed = $1" fi
This script will also give the same output as well, but we are making use of -n flag instead of -z.
Reading Multiple Arguments with For or While loop
We can use “@” variable to access every parameter passed to the script via the command line. It is a special variable that holds the array of variables in BASH. In this case, we are using it alone, so it contains the array of positional parameters passed in. We can use it to iterate over the parameters passed using loops or while loop as well.
#!/bin/bash for i in $@ do echo -e "$i\n" done
Using loops and @ variable to access the parameters as array elements.
We used a range-based for loop to iterate over till there are elements in the @ array. We simply iterate over the array and print the element. We can simply assign it, modify the values, and make the required changes to the parameters and arguments to achieve the desired outcome from the script.
We can also print the arguments using the while loop and the environmental variables of BASH.
#!/bin/bash i=$(($#-1)) while [ $i -ge 0 ]; do echo $ i=$((i-1)) done
Using while loop to iterate over the passed parameters.
We are using the variable ‘#‘ as it holds the number of parameters passed in. We initialize the number of parameters and take away one as we are going to use an array to iterate over it. So, as usual, the array’s index starts from 0. As this array is initialized from the last element or parameter passed, we need to decrement the counter until 0 to print every parameter in the order it is passed. We simply use the BASH_ARGV array to access the parameters and print its value. Also, at every iteration, we decrease the value of i- the iterator or counter by one using the arithmetic double braces. From this, we simply print every parameter passed to the script using a while loop as shown from the output screenshot.
Reading With Parameter Names
Using getopts to parse arguments and parameters
We can use the getopts program/ command to parse the arguments passed to the script in the command line/ terminal by using loops and switch-case statements.
#!/bin/bash while getopts n:c: option do case "$" in n)nation=$;; c)code=$;; esac done echo "Nation : $nation" echo "code : $code"
Using getopts to parse arguments and parameters
Using getopts, we can assign the positional arguments/ parameters from the command line to the bash variables directly. This allows us to manage the parameters nicely and in a systematic way. In the above script, we have used two arguments to store the bash variables using the getopts syntax, while loops and switch-case statements.
Printing Values of All Arguments
We can print the arguments passed to the script by a simple powerful variable ‘@’ which stores all the parameters passed.
#!/bin/bash echo "The arguments passed in are : $@"
Printing Values of All Arguments
Accessing the number of Parameters passed
We can also use the variable ‘#’ to access the number of parameters passed from the command line. The # variable basically contains the number of parameters/ arguments which are passed into the script.
#!/bin/bash echo "The number of arguments passed in are : $#"
Accessing the number of Parameters passed
The following were the process and specification of passing and parsing the variables in the bash script. The logic of shifting and making modifications to the variables is in the hands of the user. This was just a demonstration of passing in and parsing down the arguments from the command line to the script to make them more dynamic.