int main(int argc, char **argv) |
Argc is an integer. It stores the number of arguments on the command line when the program was called. This includes the name of the program itself.
Argv looks weird, but what it is is an array of C-style strings. Sometimes you see it declared as "char *argv[]," which is equivalent to the above. Element argv[i] will be a c style string containing the i-th command line argument. These are defined from 0 through argc-1.
For example, the program argc.cpp prints out argc, and then each element of argv:
#include <iostream> #include <cstdio> using namespace std; int main(int argc, char **argv) { int i; printf("Argc is %d\n", argc); printf("\n"); for (i = 0; i < argc; i++) { printf("argv[%d] = %s\n", i, argv[i]); } } |
A few examples are straightforward:
UNIX> g++ argc.cpp -o argc UNIX> argc Argc is 1 argv[0] = argc UNIX> argc 5 Argc is 2 argv[0] = argc argv[1] = 5 UNIX> argc They call me Mellow Yellow - quite right, Slick Argc is 10 argv[0] = argc argv[1] = They argv[2] = call argv[3] = me argv[4] = Mellow argv[5] = Yellow argv[6] = - argv[7] = quite argv[8] = right, argv[9] = Slick UNIX>And now a few non-straightforward examples that have mostly do to with the Unix shell. If you perform redirection of standard input or standard output, those specifications are stripped out by the shell and are not included in argc/argv:
UNIX> argc < argc.cpp Argc is 1 argv[0] = argc UNIX>You can even put those specifications at the beginning of the command -- it matters not:
UNIX> > output.txt argc < argc.cpp Shaft UNIX> cat output.txt Argc is 2 argv[0] = argc argv[1] = Shaft UNIX> < output.txt argc 1 2 3 > output2.txt 4 5 6 UNIX> cat output2.txt Argc is 7 argv[0] = argc argv[1] = 1 argv[2] = 2 argv[3] = 3 argv[4] = 4 argv[5] = 5 argv[6] = 6 UNIX>If you use single or double quotes you can put spaces into single arguments. You can use single quotes to put double quotes into arguments and vice-versa:
UNIX> argc "Jim Plank" 'Jim Plank' Argc is 3 argv[0] = argc argv[1] = Jim Plank argv[2] = Jim Plank UNIX> argc "They call him 'Thor'" Argc is 2 argv[0] = argc argv[1] = They call him 'Thor' UNIX> argc 'He said, "Quoting, it'"'s quite confusing."'"' Argc is 2 argv[0] = argc argv[1] = He said, "Quoting, it's quite confusing." UNIX>Here's how Unix derives the above string:
UNIX> argc * Argc is 19 argv[0] = argc argv[1] = argc argv[2] = argc.cpp argv[3] = argv1int argv[4] = argv1int.cpp argv[5] = argv2int argv[6] = argv2int.cpp argv[7] = argvallint argv[8] = argvallint.cpp argv[9] = clearing-output argv[10] = clearing-output.cpp argv[11] = identify_words argv[12] = identify_words.cpp argv[13] = index.html argv[14] = input.txt argv[15] = onetoten argv[16] = onetoten.cpp argv[17] = output2.txt argv[18] = output.txt UNIX> argc *.cpp Argc is 8 argv[0] = argc argv[1] = argc.cpp argv[2] = argv1int.cpp argv[3] = argv2int.cpp argv[4] = argvallint.cpp argv[5] = clearing-output.cpp argv[6] = identify_words.cpp argv[7] = onetoten.cpp UNIX>
#include <iostream> #include <cstdio> #include <sstream> using namespace std; int main(int argc, char **argv) { istringstream ss; int i; if (argc != 2) { cerr << "usage: argv1int argument\n"; return 1; } ss.str(argv[1]); if (!(ss >> i)) { fprintf(stderr, "The argument %s is not an integer.\n", argv[1]); return 1; } printf("Integer: %d\n", i); } |
First, if you want to use printf() to print to standard error, you simply call fprintf() and make the first parameter stderr.
Second, you include sstream to use stringstreams. You treat ss above just like cin to determine whether argv[1] is an integer.
UNIX> g++ argv1int.cpp -o argv1int UNIX> argv1int usage: argv1int argument UNIX> argv1int 8000 Integer: 8000 UNIX> argv1int Fred The argument Fred is not an integer. UNIX>An unfortunate part about a stringstream is that you cannot simply call the str() method to set it to another string. For example, argv2int.cpp is a logical extension to argv1int.cpp to read argv[1] into i and argv[2] into j:
#include <iostream> #include <cstdio> #include <sstream> using namespace std; int main(int argc, char **argv) { istringstream ss; int i, j; if (argc != 3) { cerr << "usage: argv1int argument argument\n"; return 1; } ss.str(argv[1]); if (!(ss >> i)) { fprintf(stderr, "Argument i -- %s is not an integer.\n", argv[1]); return 1; } printf("Argument i: %d\n", i); ss.str(argv[2]); if (!(ss >> j)) { fprintf(stderr, "Argument j -- %s is not an integer.\n", argv[2]); return 1; } printf("Argument j: %d\n", j); } |
When we run it, it fails on j, even though argv[2] does represent an integer:
UNIX> g++ argv2int.cpp -o argv2int UNIX> argv2int 10 20 Argument i: 10 Argument j -- 20 is not an integer. UNIX>This is because you have to call clear on the stringstream before calling ss.str(argv[2]). That's a drag -- try to remember it so that you don't get burnt by it when programming. To hammer this home, argvallint.cpp tests each command line argument to see it it is an integer:
#include <iostream> #include <cstdio> #include <sstream> using namespace std; int main(int argc, char **argv) { istringstream ss; int i, j; for (i = 1; i < argc; i++) { ss.clear(); ss.str(argv[i]); if (!(ss >> j)) { printf("Argument %d -- %s is not an integer.\n", i, argv[i]); } else { printf("Argument %d -- %d\n", i, j); } } } |
UNIX> g++ argvallint.cpp -o argvallint UNIX> argvallint 1 2 buckle my shoe. 3 4 get out the door. Argument 1 -- 1 Argument 2 -- 2 Argument 3 -- buckle is not an integer. Argument 4 -- my is not an integer. Argument 5 -- shoe. is not an integer. Argument 6 -- 3 Argument 7 -- 4 Argument 8 -- get is not an integer. Argument 9 -- out is not an integer. Argument 10 -- the is not an integer. Argument 11 -- door. is not an integer. UNIX>
#include <iostream> #include <cstdio> #include <sstream> using namespace std; int main(int argc, char **argv) { ostringstream ss; string s; int i; for (i = 1; i < 11; i++) ss << i << " "; s = ss.str(); cout << s << endl; } |
It creates a string containing the numbers 1 through 10 and then prints it out:
UNIX> g++ onetoten.cpp -o onetoten UNIX> onetoten 1 2 3 4 5 6 7 8 9 10 UNIX>When you want to "reuse" an ostringstream, you need to clear it, and to call its str() method with an empty string as its argument. That resets it to be empty. If you don't do it and you're not ready for it, you'll get some surprising output. For example, clearing-output.cpp attempts to print out four random integers by first putting them into an ostringstream and then printing out the string:
#include <iostream> #include <cstdio> #include <cstdlib> #include <sstream> using namespace std; int main(int argc, char **argv) { ostringstream ss, ss2; int i, j; srand48(0); printf("Not calling ss.str(\"\"):\n\n"); for (i = 0; i < 4; i++) { ss.clear(); ss << "#" << i << ": " << lrand48()%1000 << "\n"; cout << ss.str(); } cout << endl; srand48(0); printf("Calling ss2.str(\"\"):\n\n"); for (i = 0; i < 4; i++) { ss2.clear(); ss2.str(""); ss2 << "#" << i << ": " << lrand48()%1000 << "\n"; cout << ss2.str(); } } |
In the first loop, it does not call str("") at the beginning of each iteration, and as a result, the same numbers get printed out multiple times. The second loop prints each number exactly once:
UNIX> clearing-output Not calling ss.str(""): #0: 414 #0: 414 #1: 240 #0: 414 #1: 240 #2: 554 #0: 414 #1: 240 #2: 554 #3: 841 Calling ss2.str(""): #0: 414 #1: 240 #2: 554 #3: 841 UNIX>
#include <iostream> #include <cstdio> #include <sstream> using namespace std; int main(int argc, char **argv) { istringstream ss; string s; int l, w; l = 0; while (getline(cin, s)) { l++; ss.clear(); ss.str(s); w = 0; while (ss >> s) { w++; printf("Line %3d, word %3d: %s\n", l, w, s.c_str()); } printf("\n"); } } |
UNIX> g++ identify_words.cpp -o identify_words UNIX> cat input.txt There's a port on a western bay And it serves a hundred ships a day. Lonely sailors pass the time away And talk about their homes. UNIX> identify_words < input.txt Line 1, word 1: There's Line 1, word 2: a Line 1, word 3: port Line 1, word 4: on Line 1, word 5: a Line 1, word 6: western Line 1, word 7: bay Line 2, word 1: And Line 2, word 2: it Line 2, word 3: serves Line 2, word 4: a Line 2, word 5: hundred Line 2, word 6: ships Line 2, word 7: a Line 2, word 8: day. Line 3, word 1: Lonely Line 3, word 2: sailors Line 3, word 3: pass Line 3, word 4: the Line 3, word 5: time Line 3, word 6: away Line 4, word 1: And Line 4, word 2: talk Line 4, word 3: about Line 4, word 4: their Line 4, word 5: homes. UNIX>