A simple tutorial on command line parameters, as some people may not know how it is done.
-sec "What's the point?"
The point is that with command-line parameters you have no need of a human being to invoke your program -- this way, you can have, for example, a calculator with a GUI. The user opens the GUI and types in some commands. The GUI's executable invokes the calculator, for example, like this:
calc add 5 5, calc.exe returns 10. Then the GUI can display "10" in a text box. "But you can just use a separate function" I hear you say. Well yes, in this case, you could just have an "add" function. But what if your user is using a text-only display or has a very old computer? They won't be able to use the program you spent two months designing. In the case of a calculator, you could say "But who cares? There are numerous calculators". True; but for something more complex it would be better to have two executables.
Another advantage is that people don't need your source code to include your file with their project. It would certainly be easier; but unnecessary.
Yet another is that it enables you to write in two different programming languages without the need for embedding. In C++ it
is possible to embed languages like ASM or Python (I'm not sure how to embed Python, but there's a
asm("ASMCommand");
command), but personally I think it better to create a seperate file, as with ASM it would take too long to type out a large piece of code into the asm() function -- you'd have to put \n\ at the end of every line which would be difficult to read; and also because you can't be sure the person reading your code even knows ASM. It may confuse them. So for readability and practicality it would be better to have two executables. Assembler's excellent execution time would not be so evident in a calculator, but as I say, for large projects it's definately worth having it.
There are more that I won't go into right now.
-sec "So how do you do it?"
It is very easy to use command line parameters once you know how. First of all you must declare main() with the following parameters:
(int argc, char* argv[])
.
Why
argc and
argv[]? Well really, you could name them anything -- argc and argv[] are simply naming conventions. But they do have meaning --
argument
count and
argument
vector.
--subsec "Argument Count:"
argc contains the amount of arguments, separated by spaces, that were entered when the program was invoked. Let's say I have written a program to move file at arbitrary location
x to location
y. Let's say I have compiled and linked it as movefile (.exe on windows). If, for example, I opened up a terminal, and typed "movefile <filename> <frompath> <topath>"; then argc would be 4.
--subsec "Argument Vector:"
argv contains the actual arguments themselves. In argv[0] will always be the command used to invoke the program (thanks, Disch). If, for example, movefile was stored in C:\MyPrograms\ or /home/myprograms, and the current working directory (the folder your terminal is in, e.g. "C:\Users\Name>" or "name@workstation:~/home/name$" you would have to type in "C:\MyPrograms\movefile myfile mypath myotherpath" or "/home/myprograms/movefile myfile mypath myotherpath". That is what argv[0] will contain. argv[1] would be "myfile", etc.
-sec Switches:
Switches are sent to your programs as arguments themselves, but there are certain advantages to using a switch over having plain arguments. One such advantage is that you can figure out where your argument variables are. If you do not have any switches, you either have to rely on the user (big mistake) of the program to know the syntax (which would be incredibly frustrating for them), or use some kind of regular expression, which would be incredibly frustrating for you. So using a switch is definately worth it. With a switch, you can do this: "movefile -f myfile -p mypath -o myotherpath". Then you can easily find out where your arguments are:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
if (i + 1 != argc) // Check that we haven't finished parsing already
if (argv[i] == "-f") {
// We know the next argument *should* be the filename:
myFile = argv[i + 1];
} else if (argv[i] == "-p") {
myPath = argv[i + 1];
} else if (argv[i] == "-o") {
myOutPath = argv[i + 1];
} else {
std::cout << "Not enough or invalid arguments, please try again.\n";
Sleep(2000);
/*
* Sleep for 2 seconds to allow user (if any) to read above statement.
* The issue with this is that if we're a backend program to a GUI as mentioned above;
* that program would also sleep for 2 seconds. Most programs don't
* have this - the console will keep the text there until it scrolls off the page or whatever, so you may aswell leave it out.
***/
exit(0);
}
| |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
|
#include <iostream>
// When passing char arrays as parameters they must be pointers
int main(int argc, char* argv[]) {
if (argc < 5) { // Check the value of argc. If not enough parameters have been passed, inform user and exit.
std::cout << "Usage is -in <infile> -out <outdir>\n"; // Inform the user of how to use the program
std::cin.get();
exit(0);
} else { // if we got enough parameters...
char* myFile, myPath, myOutPath;
std::cout << argv[0];
for (int i = 1; i < argc; i++) { /* We will iterate over argv[] to get the parameters stored inside.
* Note that we're starting on 1 because we don't need to know the
* path of the program, which is stored in argv[0] */
if (i + 1 != argc) // Check that we haven't finished parsing already
if (argv[i] == "-f") {
// We know the next argument *should* be the filename:
myFile = argv[i + 1];
} else if (argv[i] == "-p") {
myPath = argv[i + 1];
} else if (argv[i] == "-o") {
myOutPath = argv[i + 1];
} else {
std::cout << "Not enough or invalid arguments, please try again.\n";
Sleep(2000);
exit(0);
}
std::cout << argv[i] << " ";
}
//... some more code
std::cin.get();
return 0;
}
}
| |
-sec "Words with a space:"
Where arguments or paths with a space key must be used (e.g. C:\My Path\SomeDocument or /home/some path/somedocument" the argument must be "enclosed in quotes".
-epilogue "\
Hopefully now you can understand what is going on with the whole arguments/parameters thing; and also how I titled each section :)
"
-command exit