C ++ - call input function as string

I am new to C ++ and I am writing a program that executes certain commands. My program should have about 200 commands and use strcmp

to check if a line is one of the commands seems to be slow and inaccurate to me. I am wondering if there is a function that could call a given input directly as a command.

For example:

void main() {    
    char test[60], param[10];
    std::cin >> test >> param;
    callFunction(test, param); 
}

      

NOTE. I've already searched and found a way to use maps, but what if the number of arguments for each function is different? Any help would be appreciated, thanks!

+3


source to share


5 answers


It would be good coding practice to create a class for each command and inherit those classes from a common base class with a virtual function taking a vector of arguments. In your case, the arguments are strings, so command methods can take a vector of strings as arguments and return eg. program exit code. Then there is a map, or rather a hash table, which is an unordered_map in C ++ because ordered iteration is not needed here. In this unordered_map, the keys are lowercase command names, and the values ​​are pointers to an instance of the command to process that command. An example source code is given below:



#include <unordered_map>
#include <string>
#include <cstdint>
#include <vector>
#include <iostream>
#include <memory>

enum class ExitCode : int32_t
{
    OK = 0,
    WRONG_USAGE = 1,
    // Change the values below to your specific error (exit) codes
    SOME_ERROR = 2,
    OTHER_ERROR = 3
};

class CommandProcessor
{
public:
    virtual ExitCode Go(const std::vector<std::string>& parameters) = 0;
};

class FooCommandProcessor : public CommandProcessor
{
public:
    virtual ExitCode Go(const std::vector<std::string>& parameters) override
    {
        // Implement processing of Foo command here
        return ExitCode::OK;
    }
};

class BarCommandProcessor : public CommandProcessor
{
    virtual ExitCode Go(const std::vector<std::string>& parameters) override
    {
        // Implement processing of Bar command here
        return ExitCode::OK;
    }
};

// Implement classes processing the other commands here

class CommandSelector
{
    typedef std::unordered_map<std::string, std::shared_ptr<CommandProcessor>> 
        StringCommandProcessorMap;
    StringCommandProcessorMap _scpm;
    template <class CP> void RegisterCommand(const std::string& command)
    {
        _scpm.insert(StringCommandProcessorMap::value_type(
            command, std::shared_ptr<CommandProcessor>(new CP())));
    }
public:
    CommandSelector()
    {
        RegisterCommand<FooCommandProcessor>("foo");
        RegisterCommand<BarCommandProcessor>("bar");
        // Register the rest of your commands here
    }
    ExitCode InvokeCommand(const std::string& command, 
        const std::vector<std::string>& parameters)
    {
        std::string lowercaseCommand;
        for (int i = 0; i < int(command.size()); i++)
        {
            lowercaseCommand.push_back(::tolower(command[i]));
        }
        StringCommandProcessorMap::iterator it = _scpm.find(lowercaseCommand);
        if (it == _scpm.end())
        {
            std::cout << "Unknown command: " << lowercaseCommand << std::endl;
            return ExitCode::WRONG_USAGE;
        }
        return it->second->Go(parameters);
    }
};

int main(int argc, char* argv[])
{
    if (argc < 2)
    {
        std::cout << "Usage: <your_exe_name> <command> [arguments]" << std::endl;
        return int(ExitCode::WRONG_USAGE);
    }
    std::string command(argv[1]);
    std::vector<std::string> parameters;
    for (int i = 2; i < argc; i++)
    {
        parameters.push_back(std::string(argv[i]));
    }
    CommandSelector cs;
    ExitCode ec = cs.InvokeCommand(command, parameters);
    return int(ec);
}

      

+1


source


You can call methods exec

with the required argument to run your commands



Checkout: http://linux.die.net/man/3/exec

0


source


Check the command pattern:

Encapsulate all commands / functions in their own objects. Chances are you don't want 200 different command classes, but just a few, a grouping of similar function calls with the same target and count and type argument.

Then create a string map for these command objects. All command objects have the same interface, and the differences in the number of arguments and the type of the original fancripts are encapsulated internally.

0


source


Function call table (or similar). If speed is important, use std::unordered_map

to do something like:

std::unordered_map<std::string, function> cmds;
...
cmds["mycommand"] = myCommandFunction();

      

I personally wrote a dozen different programs with static array tables with a string + function pointer and just used a simple loop to iterate over the array - usually not the slowest part of the design [if speed matters, profile your code to see where it takes time. and then optimize, but start by writing clear and simple code, don't make the code more complicated simply because you think it might be most of the time before you measured it]

An example of usage std::map

and function pointers [in this case lambda functions] can be found here: https://github.com/Leporacanthicus/lacsap/blob/master/builtin.cpp#L972

0


source


An example of my comment:

#include <string>
#include <unordered_map>
#include <iostream>

typedef void(*commandPtr)(const char* args);

std::unordered_map <std::string, commandPtr> commands;

void someCommand(const char* args)
{
    std::cout << "some command with args : " << args << std::endl;
}

int main()
{
    commands.insert(std::make_pair("someCommand", someCommand)); // add a command to the map
    std::string command, args;
    std::cin >> command >> args;
    if (commands.find(command) == commands.end()) // the command doesn't exist
        std::cout << "Command doesn't exist";
    else
        commands.find(command)->second(args.c_str()); // call the command with args
    std::cin.get();
    return 0;
}

      

This allows only one arbitrary argument to be used.

0


source







All Articles