Java状态机日期识别代码无法进入case 8的问题求助
日期格式验证状态机的执行问题
我们要识别DD/MM格式的日期(例:03/02代表2月3日),简化规则为每月30天,实现的Java代码如下:
package Tp2; import java.util.Scanner; public class EX2_Date_forme { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while (true) { System.out.println("give a string or (exit) to leave : "); String input = sc.nextLine(); if (input.equals("exit")) break; System.out.println(); Date(input); } } public static void Date(String input) { int len = input.length(); int state = 0; int tracker = 0; for (int i = 0; i < len; i++) { char c = input.charAt(i); boolean c_isBetween_zero_in_AndNine = Character.getNumericValue(c) >= 0 && Character.getNumericValue(c) <= 9; boolean c_isBetween_zero_out_AndNine = Character.getNumericValue(c) > 0 && Character.getNumericValue(c) <= 9; switch (state) { case 0: if (c == '0') { state = 1; tracker++; } else if (c == '1' || c == '2') { state = 2; tracker++; } else if (c == '3') { state = 3; tracker++; } else System.out.println("error"); break; case 1: if (c_isBetween_zero_out_AndNine) { state = 4; tracker++; } else System.out.println("error"); break; case 2: if (c_isBetween_zero_in_AndNine) { state = 4; tracker++; } else System.out.println("error"); break; case 3: if (c == '0') { state = 4; tracker++; } else System.out.println("error"); break; case 4: if (c == '/') { state = 5; tracker++; } else System.out.println("error"); break; case 5: if (c == '0') { state = 6; tracker++; } else if (c == '1') { state = 7; tracker++; } else System.out.println("error"); break; case 6: if (c_isBetween_zero_out_AndNine) { state = 8; tracker++; } else System.out.println("error"); break; case 7: if (c == '0' || c == '1' || c == '2') { tracker++; state = 8; } else System.out.println("error"); break; case 8: if (tracker == len) System.out.println("in the language"); else System.out.println("error"); break; } } } }
调试输入"01/01"时,流程能走到state=8,但for循环从未进入case 8分支,出不来预期的"in the language"提示。目前在循环后加一段判断代码能正常运行,但希望让流程进入case 8处理:
if (state == 8 && tracker == len) { System.out.println("in the language"); } else { System.out.println("error"); }
问题根源
拿"01/01"举例,字符串长度是5,for循环的i从0到4共5次迭代:
- 第5次迭代(i=4)处理最后一个字符
'1'时,state从6切换为8,tracker变成5(等于字符串长度) - 这次迭代走的是
case 6分支,执行完后循环直接结束,根本没机会进入case 8
解决办法
要让流程进入case 8,可以在for循环结束后,额外执行一次针对当前state的switch判断,补全终止状态的校验:
public static void Date(String input) { int len = input.length(); int state = 0; int tracker = 0; for (int i = 0; i < len; i++) { // 原循环内代码完全保留 char c = input.charAt(i); boolean c_isBetween_zero_in_AndNine = Character.getNumericValue(c) >= 0 && Character.getNumericValue(c) <= 9; boolean c_isBetween_zero_out_AndNine = Character.getNumericValue(c) > 0 && Character.getNumericValue(c) <= 9; switch (state) { case 0: if (c == '0') { state = 1; tracker++; } else if (c == '1' || c == '2') { state = 2; tracker++; } else if (c == '3') { state = 3; tracker++; } else System.out.println("error"); break; case 1: if (c_isBetween_zero_out_AndNine) { state = 4; tracker++; } else System.out.println("error"); break; case 2: if (c_isBetween_zero_in_AndNine) { state = 4; tracker++; } else System.out.println("error"); break; case 3: if (c == '0') { state = 4; tracker++; } else System.out.println("error"); break; case 4: if (c == '/') { state = 5; tracker++; } else System.out.println("error"); break; case 5: if (c == '0') { state = 6; tracker++; } else if (c == '1') { state = 7; tracker++; } else System.out.println("error"); break; case 6: if (c_isBetween_zero_out_AndNine) { state = 8; tracker++; } else System.out.println("error"); break; case 7: if (c == '0' || c == '1' || c == '2') { tracker++; state = 8; } else System.out.println("error"); break; case 8: if (tracker == len) System.out.println("in the language"); else System.out.println("error"); break; } } // 循环结束后补充终止状态判断 switch(state) { case 8: // 进入case 8执行校验 if (tracker == len) System.out.println("in the language"); else System.out.println("error"); break; default: // 未走到终止状态直接报错 if (tracker != len) System.out.println("error"); break; } }
这样既保留了原状态机的逻辑,又能让流程进入case 8完成最终输出,同时避免了中途重复输出错误的问题。
内容的提问来源于stack exchange,提问作者BADR EL ADRAOUI
相关产品推荐
相关产品推荐

