Reputation: 103
I'm building a set of functions in an included file, and i would like to be able to run my test main() to call the function name passed on the command line. Something like this:
void rotate (int degrees) {
/*...*/
}
void translate (int pixels) {
/*...*/
}
int main(int argc, char* argv[] ) {
const int degs = 100;
const int pix = 250;
string func = argv[1];
//call func(degs) or func(pix) based on the command line argument passed
}
I'd like to be able to run this like % a.out translate
from the command line. What is the syntax to make this work. Thanks in advance I looked for a while on this one and couldn't find anything.
Upvotes: 2
Views: 6607
Reputation: 2210
As you requested, here is an example on how you could use std::map to achieve what you want. I am using void functions with void parameters for the sake of simplicity. In your case, you will have to use void (*)(int) for the map in order to use your functions since they take ints as parameters. You will also have to find how to pass the ints themselves. You can probably do this by taking the argv arguments by pairs.
#include <iostream>
#include <map>
#include <string>
void func1() {
std::cout << "func1" << std::endl;
}
void func2() {
std::cout << "func2" << std::endl;
}
void func3() {
std::cout << "func3" << std::endl;
}
std::map<std::string,void (*)(void)> tmap = {
{"func1",&func1},
{"func2",&func2},
{"func3",&func3}
};
int main(int argc, char* argv[]) {
if (argc > 1) {
for (int i =1; i != argc; ++i) {
if (tmap.find(argv[i]) != tmap.end()) {
tmap[argv[i]]();
}
else {
std::cout << "There is no " << argv[i] << " function available." << std::endl;
}
}
}
else {
std::cout << "No functions were choosen." << std::endl;
}
return 0;
}
Upvotes: 3
Reputation: 141574
As requested...
#include <iostream>
#include <string>
#include <map>
typedef void FUNC(int);
FUNC rotate, translate;
int main(int argc, char *argv[])
{
std::map<std::string, FUNC *> m;
m["rotate"] = rotate;
m["translate"] = translate;
if ( argc > 1 )
{
FUNC *ptr = m[argv[1]];
if ( ptr )
ptr(100);
}
}
In C++11 you can use brace-enclosed initializers for m
.
If the duplication bothers you, you could even go:
#define M_ROW(funcname) m[#funcname] = funcname
Upvotes: 2
Reputation: 129374
It is not possible to do this in C or C++, because the name of the function "disappears" when you compile the code.
The common way to solve this is to use either a std::map<std::string, FunctionPtr>
or some other form of table that contains a translation between string and function pointer.
Of course a very crude version is to simply do:
if (argv[1] == std::string("translate"))
{
int x = atoi(argv[2]);
translate(x);
}
(You need the cast to std::string
or you need to use strcmp
, since using ==
between a char *
and a string literal will just compare the address of the string, and argv
isn't going to contain addresses of string literals under any reasonable circumstances)
Function pointers in std::map
could be something like this
typedef void (*FuncType)(int v);
std::map<std::string, FuncType> m;
m["translate"] = translate;
m["rotate"] = rotate;
// Convert argv[2] to integer:
int x = argv[2];
// Call function indicated by argv[1]:
m[argv[1]](x);
Upvotes: 6