1

I'm working on a project and I need a way of receiving input from the console/user and use that to run a certain part in the code without the need of elaborate switch/if:else statements. Let me give you an example.

#include <iostream>
#include <string>

using namespace std;

void foo();
void foo2();

int main(){
    string s;
    cin >> s;

    /*Take the input from cin and turn it into a function call, or some other
    form of runnable code, like so*/

    //Lets say the user inputs "run foo"
    foo();
    //Or if they input "run foo2"
    foo2();

    return 0;
}

void foo(){
    cout << "Foo works, yay :D";
}

void foo2(){
    cout << "Foo2 works, yay :D";
}

You might think I could do this with a switch or multiple if:else statements but this little code is just a small representation of what I need to do. The project requires this to be used on a large scale and I'd like it if I didn't need to use those, to save lines.

So is there any way I can do this in C++? Where the console user tells the program what to run and it runs said function?

Thanks!!

EDIT This is not a duplicate of the string to function call as this gets the input directly from the user versus from the program. As well as the answers show that you can use lua to do this since it is from user input.

  • you may want to embed Lua or some other embeddable scripting language – Bryan Chen Aug 31 '15 at 22:26
  • 1
    Use a dispatch table. – Barmar Aug 31 '15 at 22:26
  • This is a really complex question. I agree with Bryan Chen that the best generic advice is to use lua, if you need a "real" scripting language. If you just need like, command line arguments like you have for `gdb` or some other terminal program, so do a sequence of simple actions (and you don't need variables, or user defined functions), then what I would do is just make a simple grammar in `boost::spirit::qi`, parse it, and then evaluate it. Or even simpler, use `boost::program_options` to read the CL args, and then iterate over them calling corresponding functions. – Chris Beck Aug 31 '15 at 22:30

3 Answers3

4

Maybe the simplest thing would be to use a std::map of std::function objects:

std::map<std::string, std::function<void()>> funcs;
funcs[userInputString]();

Live example.

Depending on your requirements you may need something more sophisticated than this however and at some point of complexity you might want to consider embedding a scripting language like Lua.

mattnewport
  • 13,728
  • 2
  • 35
  • 39
  • You beat me by 2 mins! hah :P – Gustavo Maciel Aug 31 '15 at 22:30
  • Actually I think this could work well for the project. What would be the advantages of using Lua instead of direct coding it into the c++? I've never used lua extensively so I didn't think you could link the two or use it to do this. – Amber Sours Sep 01 '15 at 16:49
  • @SnowCrystalz the advantage of using a scripting language like Lua is that it makes it easier to extend your text interface to support more complex syntax: things like expressions, function arguments and variables. If you wanted to go beyond `run foo` to support commands like `s = foo(a + 1, bar())` for example then using a scripting language would make that relatively easy vs. a hand rolled solution. – mattnewport Sep 01 '15 at 16:55
  • @mattneport That seems more of what I need actually... Is this easy to do in lua? Or would it take me some time to write this in lua and connect the two (C++ and Lua)? – Amber Sours Sep 01 '15 at 18:51
  • @SnowCrystalz It's a while since I've worked with Lua but my experience was that it was fairly easy to integrate into a project. Creating the bindings between Lua and your C++ functions is a bit of work but there are a wide variety of libraries designed to make this easier in C++ than using the raw C API bindings: http://lua-users.org/wiki/BindingCodeToLua – mattnewport Sep 01 '15 at 19:27
  • @mattnewport Thanks! I'll check into that documentation and see if I can incorporate it! – Amber Sours Sep 01 '15 at 21:16
2

Straight-forward way:

  • Make a map of string to std::function<void()>
  • Take the cin input string
  • Explode the string by spaces to a string array
  • If the first value is "run", Search the map for the second value and if you find it, execute the function pointer.

Arguments are hard to implement this way.

Better way:

Use LUA, Squirrel, Angel Code, JS, Python, or any other C/C++ embedded language available.

Gustavo Maciel
  • 652
  • 7
  • 20
0
typedef void (*ScriptFunction)(void); // function pointer type
typedef std::map<std::string, ScriptFunction> script_map;

void some_function(void)
{
}

script_map m;
m.insert(std::make_pair("blah", &some_function));

void call_script(const std::string& pFunction)
{
script_map::const_iterator iter = m.find(pFunction);
if (iter == m.end())
{
    // not found
}

(*iter->second)();
}

call call_script(user_input); in your code
spear123
  • 1
  • 2