what is the correct way to handle multiple input command differently in c++?

前端 未结 5 681
深忆病人
深忆病人 2021-01-12 16:24

I have a program that take commands from user and it will process different commands differently. For example:

ADD_STUDENT ALEX 5.11 175
ADD_TEACHER MERY 5.4         


        
5条回答
  •  春和景丽
    2021-01-12 16:36

    Well, it's too late for much chance at upvotes, but you guys got me thinking about this...

    For robustness, you could split parsing into two stages: the first stage gets lines, and the second stage takes a line and does something with it.

    For the first stage, you can use the getline:

    #include 
    #include 
    
    void ParseLines(std::istream& source)
    {
        while(source)
        {
            // Get a line from the source.
            std::string inputLine;
            std::getline(source, inputLine);
    
            // Make a stream out of it.
            std::istringstream inputStream(inputLine);
            std::string command;
            inputStream >> command;
            if(inputStream) // Empty or bad line: skip
                HandleCommand(command, inputStream);
        }
    }
    

    The second stage handles the command. It could be something direct like this:

    void HandleCommand(const std::string& command, std::istringstream& params)
    {
        if(command == "ADD_STUDENT")
        {
            float someFloat;
            int someInt;
            params >> someFloat >> someInt;
            // add the student.
        }
        // etc.
    }
    

    But I have no shame and would implement a Factory paradigm:

    #include 
    
    typedef void (*CommandHandler)(const std::string&, std::istringstream&);
    typedef std::map CommandTable;
    
    static CommandTable gCommands; // Yep. A global. Refactor however you see fit.
    
    void HandleCommand(const std::string& command, std::istringstream& params)
    {
        CommandTable::iterator handler = gCommands.find(command);
        if(handler == gCommands.end())
        {
            // Handle "command not found" error.
            return;
        }
    
        (*(handler->second))(command, params);
    }
    
    void AddStudent(const std::string& command, std::istringstream& params)
    {
        float someFloat;
        int someInt;
        params >> someFloat >> someInt;
        // add the student.
    }
    
    // Other command handling functions here...
    
    void RegisterCommands()
    // Call this once prior to parsing anything,
    // usually one of the first things in main().
    {
        gCommands["ADD_STUDENT"] = &AddStudent;
        // ... other commands follow...
    )
    

    Haven't tested any of this, but it should be mostly there. Note any bugs in the comments.

    P.S. This is highly inefficient and will run slower than a properly designed command parser, however, it should be good enough for most jobs.

提交回复
热议问题