Java控制台输入处理
这是我在这里的第一个问题,我希望它不是基于太多的意见。我在互联网上搜索了很长一段时间,但没有找到类似的问题。Java控制台输入处理,java,validation,input,console,Java,Validation,Input,Console,这是我在这里的第一个问题,我希望它不是基于太多的意见。我在互联网上搜索了很长一段时间,但没有找到类似的问题。 我需要编写一个Java程序,从控制台读取命令,验证输入,获取参数并将其传递到另一个类。 我可以做什么和使用什么(大学)有一些限制。 只允许包java.util、java.lang和java.io 每种方法只能有80行 每行只能有120个字符长 我不允许使用System.exit/Runtime.exit 终端类用于处理用户输入Terminal.readLine()将从控制台读取一行,如
我需要编写一个Java程序,从控制台读取命令,验证输入,获取参数并将其传递到另一个类。
我可以做什么和使用什么(大学)有一些限制。
- 只允许包java.util、java.lang和java.io
- 每种方法只能有80行
- 每行只能有120个字符长
- 我不允许使用System.exit/Runtime.exit
- 终端类用于处理用户输入
将从控制台读取一行,如Terminal.readLine()
Scanner.nextLine()
runInteractionLoop()
method太长)。我是这样做的:private static boolean quit = false;
...
public static void main(String[] args) {
...
while (quit == false) {
runInteractionLoop();
}
}
private static runInteractionLoop() {
Matcher m;
String query = Terminal.readLine;
m = Pattern.compile("sliding-window (\\d+) (-?\\d+(?:\\.\\d+)?;)*(-?\\d+(?:\\.\\d+)?)").matcher(query);
if (m.matches()) {
xyz.doSth(Integer.parseInt(m.group(1)), ......);
...
return;
}
m = Pattern.compile("record ([a-z]+) (-?\\d+(?:\\.\\d+)?)").matcher(query);
if (m.matches()) {
xyz.doSthElse(m.group(1), Double.parseDouble(m.group(2)));
return;
}
...
if (query.equals("quit")) {
quit = true;
return;
}
Terminal.printError("invalid input");
}
有什么想法吗?我将非常感谢您的建议。谢谢 编辑/更新:
我决定将验证分为两种方法——每一半命令一种。看起来很难看,但通过了Uni的checkstyle要求然而,如果有人能为我的问题提供更好的解决方案,我还是会非常高兴的——为了将来(因为我显然不知道如何使这个问题变得更漂亮、更短和/或更高效)。我想你可以尝试类似这样痛苦的方法,将所有内容都分成一系列方法调用:
private static runInteractionLoop() {
Matcher m;
String query = Terminal.readLine;
m = Pattern.compile("sliding-window (\\d+) (-?\\d+(?:\\.\\d+)?;)*(-?\\d+(?:\\.\\d+)?)").matcher(query);
if (m.matches()) {
xyz.doSth(Integer.parseInt(m.group(1)), ......);
...
return;
} else {
tryDouble(query, m);
}
}
Private static tryDouble(String query, Matcher m) {
m = Pattern.compile("record ([a-z]+) (-?\\d+(?:\\.\\d+)?)").matcher(query);
if (m.matches()) {
xyz.doSthElse(m.group(1), Double.parseDouble(m.group(2)));
return;
} else {
trySomethingElse(query, m);
}
}
Private static trySomethingElse(String query, Matcher m) {
...
if (query.equals("quit")) {
quit = true;
return;
}
Terminal.printError("invalid input");
}
通过将匹配工作委托给子方法,可以将每种可能性归结为两行(如果分隔行上必须有结束括号,则为三行):
if ( Matcher m = matches( query, "sliding-window (\\d+) (-?\\d+(?:\\.\\d+)?;)*(-?\\d+(?:\\.\\d+)?)") != null)
xyz.doSth(Integer.parseInt(m.group(1)), ......);
else if ( Matcher m = matches( query, "record ([a-z]+) (-?\\d+(?:\\.\\d+)?)") != null)
xyz.doSthElse(m.group(1), Double.parseDouble(m.group(2)));
...
else
private Matcher matches( String input, String regexp)
{
Matcher result = Pattern.compile(regexp).matcher(input);
if ( result.matches() )
return result;
else
return null;
}
我会用一个抽象类
CommandValidator
来解决这个问题:
public abstract class CommandValidator {
/* getter and setter */
public Matcher resolveMatcher(String query) {
return Pattern.compile(getCommand()).matcher(query);
}
public abstract String getCommand();
public abstract void doSth();
}
将为每个处理程序实现16个不同的CommandValidator,并以不同的方式实现抽象方法:
public class IntegerCommandValidator extends CommandValidator {
@Override
public String getCommand() {
return "sliding-window (\\d+) (-?\\d+(?:\\.\\d+)?;)*(-?\\d+(?:\\.\\d+)?)";
}
@Override
public void doSth() {
/* magic here, parameter input the matcher and xyz, or have it defined as field at the class */
// xyz.doSth(Integer.parseInt(m.group(1)), ......);
}
}
由于在CommandValidator
中需要匹配器,因此可以将其设置为类的字段,或者将其放入doSth()
方法中
然后,您可以实例化列表中的每个具体验证器,并迭代每个验证器,解析匹配器并查看它是否匹配:
private static Set<CommandValidator> allConcreteValidators;
public static void main(String[] args) {
/* */
allConcreteValidators.add(new IntegerCommandValidator());
/* */
while (quit == false) {
runInteractionLoop();
}
}
private static runInteractionLoop() {
String query = Terminal.readLine;
for (CommandValidator validator : allConcreteValidators) {
if (validator.resolveMatcher(query).matches()) {
validator.doSth();
}
}
}
私有静态设置AllConcreteValidator;
公共静态void main(字符串[]args){
/* */
添加(新的IntegerCommandValidator());
/* */
while(quit==false){
runInteractionLoop();
}
}
私有静态runInteractionLoop(){
字符串查询=Terminal.readLine;
for(CommandValidator验证程序:allConcreteValidators){
if(validator.resolveMatcher(query.matches()){
validator.doSth();
}
}
}
当然,如果有一个验证器适合并处理您没有定义任何验证器的情况,那么您以前可以构建一个查找方法
对于你的运动来说,可能有点过度设计了。如果具体验证器也共享相同的Doth magic,那么您可以将该命令输入到具体验证器的构造函数中。
Ofc您应该为这些类找到更好的名称,因为它不仅是一个验证器,而且还有一些不同的功能。您的意思是不允许您使用java.util.regex吗?@Heri不,我可以使用java.util、java.io和java.lang包中的所有类,但只能使用这些类。目前的情况是,我可能会创建另一个方法
runInteractionLoop2()
,并将验证的一半转移到该方法上——但这就像#@$一样难看!这不是一个明确的答案。regex是java.util的一个子包。你是否可以使用它?16种不同的可能性到底有什么不同?是的,痛苦是正确的词。。。这是我的最后一个选择,只需为每个查询添加一个方法,该查询需要多个线性行进行验证。这将使我精确到80行。是的,这看起来是一个很好的解决问题的方法。稍后我将尝试此方法,并报告它是否与我的Uni的限制性检查样式一起工作。如果您使用的是java8,您甚至可以使用一个或两个线性程序来解决它,如果您定义了前几个查找表(最小值:命令字符串和相应处理程序之间的映射),嗯。。。你确定这样行吗?由于匹配(字符串输入,字符串regexp)
返回一个匹配器
,if语句的布尔值是多少?另外,我对Java8解决方案非常感兴趣:)我对查找表的建议将首先涉及对不同命令的深入分析(如何区分它们,以及它们都有哪些共同点,哪些命令需要哪些类型的参数等等)。看起来要做很多工作。这很有趣!!对于这个练习来说,确实有点过度设计了,但是看起来很好,结构也很好。我喜欢这个,谢谢!