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 Aug 30 18:20 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
makes 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.
We call this quoting, also, even though no quote characters
are involved.
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.