#include <string.h>
#include <stdlib.h>
#define TRUE 1
#define FAULSE 0
typedef enum
{
EMPTY,
STRING
}Kind;
typedef struct Arg
{
char* name;
char* option;
char* description;
Kind kind;
void (*action)();
}Arg;
static void action_help()
{
printf("this is -help\n");
}
static void action_string(char* op)
{
printf("this is option:%s\n",op);
}
static Arg args[] =
{
{
"help",
"<>",
"display all option",
EMPTY,
action_help
},
{
"test",
"<string>",
"test the Kind_String",
STRING,
action_string
},
{
0,0,0,0,0
}
};
void scan_args(int argc, char** argv)
{
int idx = 1;
char* filename = NULL;
int found = FAULSE;
for (idx = 1; idx < argc; idx++)
{
char* arg = argv[idx];
if (arg[0] != '-')
{
if (filename == NULL)
filename = arg;
else
{
printf("only one file\n");
exit(0);
}
continue;
}
int i;
for (i = 0; args[i].name != 0; i++)
{
if (strcmp(args[i].name, arg+1) == 0)
{
found = TRUE;
switch(args[i].kind)
{
case EMPTY:
args[i].action();
break;
case STRING:
idx++;
args[i].action(argv[idx]);
break;
default:
printf("invalid kind\n");
exit(0);
}
break;
}
}
if (!found)
{
printf("invalid option");
exit(0);
}
}
}
上面是一段用C实现的命令行系统。每一个参数都是一个结构体,在结构体里面有一个函数指针。当模式匹配到这个参数时,会通过这个指针调用相应的函数。
通过一个结构体数组存放所有可能的参数,数组的最后一个元素设为零,方便遍历数组的时候当作结束标志。
同样的问题,也可用java实现。
在最近的java8里面,加入了lamda。可以很方便的实现单函数接口。
package testcmd;
public class Commandline {
static interface F
{
void f(String s);
}
static enum Kind
{
EMPTY,
STRING
}
static class Arg
{
String name;
String option;
String description;
Kind kind;
F action;
public Arg(String name, String option, String description, Kind kind, F action)
{
this.name = name;
this.option = option;
this.description = description;
this.kind = kind;
this.action = action;
}
}
private Arg[] args=
{
new Arg("help", "<>", "display all option", Kind.EMPTY, (s)->
{
System.out.println("this is -help");
}),
new Arg("test", "<string>", "for test", Kind.STRING, (s)->
{
System.out.println(s);
}
)
};
public void scan(String[] args)
{
String filename = null;
boolean found = false;
for (int i = 0; i<args.length; i++)
{
if (!args[i].startsWith("-"))
{
if (filename == null)
filename = args[i];
else
{
System.out.println("only one filename");
System.exit(0);
}
}
else
{
for (Arg arg : this.args)
{
if (!arg.name.equals(args[i].substring(1)))
continue;
found = true;
switch (arg.kind)
{
case EMPTY:
arg.action.f("");
break;
case STRING:
i++;
arg.action.f(args[i]);
break;
default:
found = false;
System.out.println("invalid kind");
System.exit(0);
break;
}
break;
}
if (!found)
{
System.out.println("invalid option");
System.exit(0);
}
}
}
}
}
在这段代码里面, 用单函数接口当作函数指针。lamda可以不需要接口的实现类而实现接口规定的方法。 而C中的结构体在java中用了一个静态的内部类实现。