2

I'm writing a program where a user can input something like

add 5 2

or

define foo

Right now the only way I know to handle this input is a bunch of if/else if statements, ie

if(args[0] == "add") add();
else if (args[0] == "define") define();
else print("Command not found.");

Is there a better way to do this, or maybe some sort of data structure/algorithm that's standard for these types of inputs? I'm using Java specifically, but I'd prefer a language-agnostic answer if possible. Thanks!

Austin Gayler
  • 4,038
  • 8
  • 37
  • 60

4 Answers4

3

You could use a switch statement:

switch (args[0]) {
    case "add":
        // do your adding stuff
        break;
    case "define":
        // do your defining stuff
        break;
    default:
        // command not found
}

switch is a common feature in most languages (some languages use different syntax, for example Ruby uses case/when instead of switch/case). It only works on Strings starting from Java 1.7 though.

Also, some languages have Dictionarys and functions in variables, so for example in Ruby you could do this:

myDictionary = { "add" => someFunctionToAddStuff,
                 "define" => anotherFunction }
myDictionary["define"] # returns anotherFunction
tckmn
  • 57,719
  • 27
  • 114
  • 156
  • 3
    +1. You might want to add that it works only in SE 7. and perhaps to mention the difference between `==` and `equals`. – Maroun May 12 '13 at 20:55
3

Design pattern Command can be used for this goals. For example:

abstract class Command {
    abstract public String getCommandName();
    abstract public String doAction();
}

To define you own function just implement Command class:

class AddCommand extends Command {
    @Override
    public String getCommandName() {
        return "add";
    }

    @Override
    public String doAction() {
        // do your action
    }
}

then your main class should looks like:

public class Main {

    private static Map<String, Command> commands = new HashMap<String, Command>();

    private static void init() {
        Command addCommand = new AddCommand();
        commands.put(addCommand.getCommandName(), addCommand);
    }

    public static void main (String[] args) {
        init();
        if (args[0] != null) {
            Command command = commands.get(args[0]);
            if (command != null) {
                System.out.println(command.doAction());
            } else {
                System.out.println("Command not found");
            }
        }
    }
Patison
  • 2,591
  • 1
  • 20
  • 33
2

I've made the (bad) assumption here that you're asking about command line arguments based off of the way you're using args. But I may be wrong about that. Let me know:

There's a better way to do this, but you may have to change the way your input is written. In fact, there are many libraries for this. A few are mentioned here: How to parse command line arguments in Java? Here are some of the options, inlined for convenience:

Community
  • 1
  • 1
Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • an example usage would be nice. there is a lot of benefit using something like commons cli, but it might not be self-evident without an example. – eis May 12 '13 at 20:58
  • @eis The sample given in that first link is very good and is just a click away. – Daniel Kaplan May 12 '13 at 20:59
1

Depending on how complex your input is you can use either handcrafted solution using Command and/or Interpreter pattern or you can employ free XText framework.

Interpreter design pattern is very useful if your grammar is not too complex, but program input conforms to a DSL (Domain Specific Language). In your case, inputs add 5 2 and define foo look like a part of larger grammar. If so, go with Interpreter. If the grammar is complex, however, then the best approach is to utilize DSL-generation-library like XText.

In case you wanted parse command line arguments you should have tried Apache Commons CLI library.

When it comes to Java, however, there is one more library worth checking - Cliche. Its main pros are extreme simplicity and annotation-driven model. Please find an example below:

// Cliche usage example
public class Calculator {
    @Command
    public void define(String variable) { ... }

    @Command
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) throws IOException {
        ShellFactory
          .createConsoleShell("my-prompt", "", new Calculator())
          .commandLoop();
    }
}
czerwin
  • 972
  • 8
  • 10