Reputation: 117
I have a problem with command line parameters. I finished the program so I can start it like this from command line:
program.exe test.txt copy_test.txt
Basically, my program does the following :
BUT (always that but?!), I should start the program from command line like this:
program.exe -input=test.txt -output=copy_test.txt
And I don't know how to do that. I researched, but I didn't find any help :(
Please respond.
#include <string>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;
int main ( int argc, char* argv[])
{
ifstream in(argv[1]);
ofstream out(argv[2]);
vector <string> sV;
string line;
while (in >> line)
sV.push_back(line);
for ( int i = 0; i < sV.size(); i++)
sort ( sV.begin(), sV.end () );
for ( int i = 0; i < sV.size(); i++)
out << sV[i] << endl;
cin.get();
return 0;
}
Upvotes: 3
Views: 2530
Reputation: 636
I'm a bit late to the party with this, but I'll provide an updated answer. You can actually get the functionality that you want in C++ with a little work using 'getopt'. Using getopt_long()
you can create either single character options (like -c
) or named options (like --input
). You can also use getopt_long_only()
which will allow you to pass named options with only a single dash. See for example here or this answer.
Example
Here is an example that should accomplish what you're trying to do:
#include <iostream>
#include <getopt.h>
#include <map>
#include <string>
int main (int argc, char** argv)
{
// Create the variables to store your parameters
std::map<std::string, std::string> input_parameters ;
input_parameters["input"] = "default_in" ; // Storage for input
input_parameters["output"] = "default_out" ; // Storage for output
// Create variables to hold your parameters
const struct option longopts[] =
{
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{0,0,0,0} // This tells getopt that this is the end
};
// Some parameters for getopt_long
int c(0);
// Get the options from the command line
while (c != -1) {
int option_index(-1) ;
// Read the next command line option
// Note here that the ':' after the 'i' and 'o' denotes that
// it requires an argument
c = getopt_long(argc, argv, "i:o:", longopts, &option_index) ;
// If the option is valid, fill the corresponding value
if ((c>0)&&(option_index>=0)) {
std::cout << option_index << std::endl;
input_parameters[longopts[option_index].name] = optarg ;
}
switch (c) {
case 'i':
// Fill input option
input_parameters["input"] = optarg ;
case 'o':
// Fill output option
input_parameters["output"] = optarg ;
case '?':
// getopt_long printed an error message
break ;
}
}
std::cout << "input = " << input_parameters["input"] << std::endl;
std::cout << "output = " << input_parameters["output"] << std::endl;
return 0 ;
}
Note that here, you would run this leaving a space between the parameter and the value you want to pass to it. This will produce the following:
$ ./myscript --input inputfile.txt --output outputfile.txt
input = inputfile.txt
output = outputfile.txt
or
$ ./myscript -i inputfile.txt -o outpufile.txt
input = inputfile.txt
output = outputfile.txt
You can also use --input
and -i
interchangeably (similarly with --output
and -o
).
Begin shameless plug (my own CLOptions code that is built around getopt)
I was actually a little disgruntled with the amount of work it took to get the full blown functionality of getopt with parameters that could be either boolean, double, int, or string. I also had to create an entirely new implementation in EVERY PROJECT! So, instead I put together a quick class called "CLOptions" so I could #include "CLOptions.h"
in my code (everything is in a single file) and now I only need one line to define each additional option. It also creates the -h
or -help
options for printing help information for you! It includes functionality for getting each parameter as either a bool, double, int, or string depending on how you define each parameter. You can take a look at it on GitHub here with an example of how the above method could be implemented. Note that the class is C++11 and will require the -std=c++11
at compile time (although if someone asks, I can try and code up a C version).
Although I haven't tried them, there's also a host of other command line programs that have been designed by other people to solve this problem (for example options or dropt). You can probably find them by googling around.
Upvotes: 0
Reputation: 881103
Well, with your new format arguments, you can't just pass them as-is to the stream constructors.
You will have to check if they start with a specific string, such as with strncmp
and then pass the address of the relevant bit such as argv[1]+8
for the input type.
Since you're providing --input=
type prefixes, you may also want to handle the possibility that they may be in the other order as well.
For example, you can replace:
int main (int argc, char* argv[]) {
ifstream in(argv[1]);
ofstream out(argv[2]);
with something like:
int main (int argc, char* argv[]) {
char *infile = 0;
char *outfile = 0;
for (int i = 1; i < argc; i++) {
if (strncmp (argv[i], "--input=", 8) == 0) {
infile = argv[i] + 8;
} else {
if (strncmp (argv[i], "--output=", 9) == 0) {
outfile = argv[i] + 9;
} else {
std::cerr << "Invalid argument [" << argv[i] << "]" << std::endl;
return -1;
}
}
}
if ((infile == 0) || (outfile == 0)) {
std::cerr << "Need to specify input and output file" << std::endl;
return -1;
}
ifstream in(infile);
ofstream out(outfile);
Upvotes: 0
Reputation: 34038
You could eliminate the need for advanced users to have to type unnecessary text each time they run your program and instead offer a -help switch that displays usage.
This is generally the approach most command line programs take, and is the reason why many command line enthusiasts appreciate the simplicity and power of the command line.
Another option would be to offer both methods, as some users may prefer the longer method.
Upvotes: 0
Reputation: 26060
You should parse main
's argv
arguments in order to check whether they start by -input
, -output
etc etc.
Doing this from scratch is a hell, but luckily there are many useful libraries to do this, like boost.program_options
Upvotes: 7