题
为了解析玩家命令,我最常使用 分裂 方法通过分隔符分割字符串,然后通过一系列来计算出其余部分 if
或 switch
es.Java 中解析字符串有哪些不同的方法?
解决方案
我假设您正在尝试使命令界面尽可能宽容。如果是这种情况,我建议您使用类似于以下的算法:
- 读入字符串
- 将字符串拆分为标记
- 使用字典将同义词转换为通用形式
- 例如,将“hit”、“punch”、“strike”和“kick”全部转换为“hit”
- 在无序、包容的基础上执行操作
- 无序 - “打猴子的脸”与“打猴子的脸”是一样的
- 包括的 - 如果命令应该是“打猴子的脸”并且他们提供“打猴子”,您应该检查有多少个命令匹配。如果只有一个命令,则执行此操作。拥有命令优先级甚至可能是一个好主意,即使有匹配项,它也会执行顶级操作。
其他提示
我真的很喜欢正则表达式。只要命令字符串相当简单,您就可以编写一些正则表达式,这些正则表达式可能需要几页代码来手动解析。
我建议你看看 http://www.regular-expressions.info 有关正则表达式的详细介绍以及 Java 的具体示例。
手动解析很有趣......一开始:)
在实践中,如果命令不是很复杂,您可以像命令行解释器中使用的那样对待它们。您可以使用以下库的列表: http://java-source.net/open-source/command-line. 。我认为你可以从 阿帕奇公共 CLI 或者 参数4j (使用注释)。它们有详细的文档记录并且使用起来非常简单。它们自动处理解析,您唯一需要做的就是读取对象中的特定字段。
如果您有更复杂的命令,那么创建正式语法也许是一个更好的主意。有一个非常好的库,带有图形编辑器、调试器和语法解释器。它被称为 ANTLR (和编辑 ANTLRWorks)并且它是免费的:)还有一些示例语法和教程。
我会看看 Java 迁移 的 佐克, ,并倾向于简单的 自然语言处理器 (由标记化或正则表达式驱动)如下所示(来自此链接):
public static boolean simpleNLP( String inputline, String keywords[]) { int i; int maxToken = keywords.length; int to,from; if( inputline.length() = inputline.length()) return false; // check for blank and empty lines while( to >=0 ) { to = inputline.indexOf(' ',from); if( to > 0){ lexed.addElement(inputline.substring(from,to)); from = to; while( inputline.charAt(from) == ' ' && from = keywords.length) { status = true; break;} } } return status; }
...
在我的书中,任何能让程序员有理由再次关注 Zork 的东西都是好的,只要留意 Grues。
...
Sun 本身建议远离 StringTokenizer 并使用 String.spilt 方法。
您还需要查看 Pattern 类。
另一次投票给 ANTLR/ANTLRWorks。如果您创建该文件的两个版本,一个包含用于实际执行命令的 Java 代码,另一个不包含(仅包含语法),那么您就拥有了该语言的可执行规范,这对于测试非常有用,对于文档来说是一个福音,如果您决定移植它,可以节省大量时间。
如果这是为了解析命令行我建议使用 公共客户端.
Apache Commons CLI 库提供了用于处理命令行界面的 API。
尝试 JavaCC Java 的解析器生成器。
它有很多解释语言的功能,并且在 Eclipse 上得到了很好的支持。
@CodingTheWheel 这是你的代码,经过一些清理并通过 eclipse (控制键+转移+F)并插入回此处:)
包括每行前面的四个空格。
public static boolean simpleNLP(String inputline, String keywords[]) {
if (inputline.length() < 1)
return false;
List<String> lexed = new ArrayList<String>();
for (String ele : inputline.split(" ")) {
lexed.add(ele);
}
boolean status = false;
to = 0;
for (i = 0; i < lexed.size(); i++) {
String s = (String) lexed.get(i);
if (s.equalsIgnoreCase(keywords[to])) {
to++;
if (to >= keywords.length) {
status = true;
break;
}
}
}
return status;
}
一个简单的空格字符串标记器应该可以工作,但是实际上有很多方法可以做到这一点。
这是使用分词器的示例:
String command = "kick person";
StringTokenizer tokens = new StringTokenizer(command);
String action = null;
if (tokens.hasMoreTokens()) {
action = tokens.nextToken();
}
if (action != null) {
doCommand(action, tokens);
}
然后标记可以进一步用于参数。这一切都假设参数中没有使用空格......因此您可能想要推出自己的简单解析机制(例如获取第一个空格并使用之前的文本作为操作,或者如果您不介意速度影响则使用正则表达式),只需将其抽象出来以便可以使用任何地方。
如果语言非常简单,就像
动词名词
然后用手劈开效果很好。
如果它更复杂,你真的应该考虑像 ANTLR 或 JavaCC 这样的工具。
我在 ANTLR (v2) 上有一个教程 http://javadude.com/articles/antlrtut 这会让您了解它是如何工作的。
指挥官 看起来相当不错,虽然我还没有测试过。
如果您的文本包含一些分隔符,那么您可以 split
方法。
如果文本包含不规则字符串意味着其中格式不同,那么您必须使用 regular expressions
.
split方法可以将一个字符串分割成指定子串表达式的数组 regex
。其论证有两种形式,即:分裂 (String regex
) 并拆分 (String regex, int limit
),它分裂了(String regex
)实际上是通过调用split(String regex, int limit)来实现的, 限制为 0. 。然后,当 限制> 0 和 限制<0 代表什么?
当。。。的时候 jdk 解释:什么时候 限制> 0 子数组长度达到限制,也就是说,如果可能的话,可以 限制-1 细分,保留为子字符串(除了 limit-1 次字符有字符串分裂结束);
限制<0 表示数组长度没有限制;
限制 = 0 字符串末尾的空字符串将被截断。StringTokenizer
类是出于兼容性原因而保留的遗留类,所以我们应该尽量使用String类的split方法。参考 关联