CS253: Software Development with C++

Spring 2021

Arguments

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

argc & argv

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

No arguments given

% g++ -Wall ~cs253/Examples/args.cc
% ./a.out
argc: 1
argv[0]: “./a.out”

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 18688 Apr 25 20:24 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”

More Quoting

In general, 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”

The > 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*”

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”