Show Lecture.Arguments as a slide show.
CS253 Arguments
The Argument Clinic
Program
Here is a program, args.cc, that displays
all its arguments in “
curly quotes”
:
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << "argc: " << argc << '\n';
for (int i=0; i<argc; i++)
cout << "argv[" << i << "]: “" << argv[i] << "”\n";
}
#include <iostream>
using namespace std;
int main(int argc, char *argv[]) {
cout << "argc: " << argc << '\n';
for (int i=0; i<argc; i++)
cout << "argv[" << i << "]: “" << argv[i] << "”\n";
}
- argc is the length of argv.
- argv is a C array of C strings.
- If, for example,
argc==3
, then argv contains three strings:
argv[0]
: the program name
argv[1]
: the first real argument
argv[2]
: the last real argument.
- Unlike most arrays,
argv[argc]
does exist, and
contains a null pointer (nullptr). Not an zero-length string—a null
pointer.
No arguments given
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out
argc: 1
argv[0]: “./a.out”
- Even though no explicit arguments were given, argv always
contains at least one entry,
argv[0]
, the program name.
Therefore, argc must be at least 1.
- It’s not a special case; argv is simply the all words typed,
including the first one, the command itself.
Arguments given
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out red white blue
argc: 4
argv[0]: “./a.out”
argv[1]: “red”
argv[2]: “white”
argv[3]: “blue”
Three arguments were given, but argc==4
, because the program name
is argv[0]
. That counts for one.
Program name
The -o
option to g++ names the resulting program something other
than a.out
:
% g++ -Wall -o war ~cs253/Examples/args.cc
% ls -l
total 20
-rwx------ 1 cs253 class 18744 Nov 22 02:45 war
% ./war famine pestilence death
argc: 4
argv[0]: “./war”
argv[1]: “famine”
argv[2]: “pestilence”
argv[3]: “death”
That’s why we use argv[0]
in error messages—it’s
always the name of the program.
Quoting
Normally, bash splits the argument string on whitespace. Quoting with
"
double quotes"
or '
single quotes'
protects the spaces:
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out Earth "Air Fire" 'Water'
argc: 4
argv[0]: “./a.out”
argv[1]: “Earth”
argv[2]: “Air Fire”
argv[3]: “Water”
Air Fire
is a single argument, argv[2]
.
- The
“
curly quotes”
were generated by the program itself.
- The
"
double"
or '
single'
quotes do not get
sent to the program—bash removes them.
More Quoting
Backslash makes ordinary things special (\n
) and
special things ordinary (\"
):
cout << "They call me \"Bonehead\".\n";
They call me "Bonehead".
Putting \
before a space prevents it from breaking arguments apart:
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out Peter Flopsy\ Mopsy Cotton-tail
argc: 4
argv[0]: “./a.out”
argv[1]: “Peter”
argv[2]: “Flopsy Mopsy”
argv[3]: “Cotton-tail”
The \
prevented the following space from breaking up words.
Instead, the space was treated as just another character.
Special characters
Many characters have meaning in bash: `~#$&*(){}[]\|;'"<>?
.
These are called special characters or metacharacters.
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out >foo
% cat foo
argc: 1
argv[0]: “./a.out”
>
sent the output of ./a.out
to the file foo
.
a.out
did not get an argument >foo
.
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out ">foo"
argc: 2
argv[0]: “./a.out”
argv[1]: “>foo”
Quoting prevented >
from being treated specially.
Wildcards
% echo abcdefghijklmnopqrstuvwxyz >a-b-c
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out *
argc: 3
argv[0]: “./a.out”
argv[1]: “a-b-c”
argv[2]: “a.out”
% ./a.out "*"
argc: 2
argv[0]: “./a.out”
argv[1]: “*”
% ./a.out zulu*
argc: 2
argv[0]: “./a.out”
argv[1]: “zulu*”
- Some characters, such as
*
, are wildcards for matching filenames.
- The
*
wildcard expands to the names of all the files in that
directory.
zulu*
would match all files starting with zulu
, but there
are none, so it remains zulu*
.
Redirection
bash uses <
, >
, and |
to reroute standard input/output.
% date >now
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out now
argc: 2
argv[0]: “./a.out”
argv[1]: “now”
% ./a.out <now
argc: 1
argv[0]: “./a.out”
Note the difference. In the first run, now
is an argument.
In the second run, bash runs ./a.out
with its standard
input attached to the file now
, and does not pass
now
as an argument.
Pipe
% date >now
% g++ -Wall ~cs253/Examples/args.cc
% ./a.out <now
argc: 1
argv[0]: “./a.out”
% cat now | ./a.out
argc: 1
argv[0]: “./a.out”
- These two
a.out
runs are almost identical.
- The first is better: the file
now
is attached to a.out
’s standard
input.
- In the second, the cat program reads the file
now
, and writes it
to its own standard output, which is attached to a pipe.
a.out
’s standard input is attached to other side of the
same pipe. The two programs execute simultaneously,
writing & reading.
- On a single-CPU machine, they can’t really run
simultaneously—they take turns, each a millisecond or so.
It’s effectively simultaneous.