第一次个人编程作业

这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系)
这个作业要求在哪里 第一次个人编程作业
这个作业的目标 实现功能、熟练使用git和GitHub
作业正文 如下
其他参考文献 如下

GitHub仓库地址:learn-programming

看到题目零碎的想法

  • 木兰
  • 留学生的文言文编程语言
  • C语言的宏定义

零碎的想法对问题的解决并没有什么帮助,所以开始搜相关案例

搜索

搜索关键字“中文编程”,意外看到了一个Github项目

中文编程的历史, 现状和展望

Java采用Unicode字符集,所以变量、方法名、类名等都可以定义为中文,所以有一种实现“中文编程”的方式就是把类名、变量名都定义为中文,但是这种方式还是不能脱离Java的关键字,所以这种方方式不符合这次的要求

开心一下-实现基于Java一个中文编程语言

没有找到相关案例,最后就从语义的角度开始分析:可以通过截取字符串来获取关键词、变量和常量,再进行逻辑操作

分析

需求分析

  • 整数变量定义、赋值
  • 加减运算
  • 输出变量或字符串
  • 三目运算:如果 则 否则

需要解决的问题

  • 字符串截取
  • 字符串语义判断
  • 异常处理
  • 负数,多位数

遇到的一些坑

  • 字符串split的时候左右边的空格会被加入到split返回的数组

完整代码

主函数

public class DemoMain {

    public static void main(String[] args) {
        Map map = new HashMap();

        Scanner sc = new Scanner(System.in);
        while (true) {
            Utils.callFunction(sc.nextLine().trim(), map);
        }
    }
}

Utils类


public class Utils {
    public static String numWords = "零一二三四五六七八九十";
    
    /**
     * 调用方法
     * @param str
     * @param map
     */
    public static void callFunction(String str, Map map) {
        String[] split = str.trim().split(" ");
        String keyword = split[0];

        if (map.get(keyword) != null) {
            Utils.manipulateNum(str, map);
        } else {

            switch (keyword) {
            case "整数":
                // System.out.println(map.get("钱包"));// 不存在返回null
                int num = Utils.assignInt(split);
                map.put(split[1], num);
                break;
            case "看看":
                Utils.printOut(split, map);
                break;
            case "如果":
                Utils.ternaryOperator(str, map);
                break;
            default:
                throw new IllegalArgumentException("judgeOperator 没有对应的判断符号请输入(整数、看看、如果): " + keyword);
            }
        }
    }

    @Test
    public void testCall() {
        Map map = new HashMap();
        callFunction("整数 气温 等于 十", map);
        callFunction("气温 减少 三", map);
        callFunction("气温 增加 二", map);
        callFunction("看看 气温", map);
        callFunction("如果 气温 大于 八 则 看看 “你好,世界” 否则 看看 “冻死我了”", map);
        //
        callFunction("整数 钱包 等于 零", map);
        callFunction("钱包 增加 四", map);
        callFunction("钱包 减少 一", map);
        callFunction("看看 钱包 ", map);
        callFunction("看看 “字符串”", map);
        callFunction("如果 钱包 大于 二 则 看看 “钱太多了” 否则 看看 “我穷死了”", map);
    }
    
    /**
     *  赋值整数变量
     * @param array
     * @return
     */
    public static int assignInt(String[] array) {
        // 先考虑一位情况
        return toNum(array[3]);
    }

    /**
     * 输出字符串或者变量
     * @param array
     * @param map
     */
    public static void printOut(String[] array, Map map) {

        String printStr = array[1];
        if (printStr.contains("“") && printStr.contains("”")) {
            System.out.println(printStr.replace("“", "").replace("”", ""));
        } else {
            System.out.println(toChStr(map.get(printStr)));
        }
    }
    @Test
    public void testPrintOut() {
        

        Map map = new HashMap();
        map.put("钱包", 10);
        Utils.printOut("看看 钱包 ".split(" "), map);
        Utils.printOut("看看 “字符串” ".split(" "), null);

    }
    
    
    
    /**
     * 三目运算
     * @param str
     * @param map
     */
    public static void ternaryOperator(String str, Map map) {
        // 如果 钱包 大于 十 则 看看 “钱太多了” 否则 看看 “我穷死了”
        // 先不考虑三目嵌套三目的情况
        String statement1 = str.substring(0, str.indexOf("则")).replace("如果", "");
        String statement2 = str.substring(str.indexOf("则"), str.indexOf("否则")).replace("则", "");
        String statement3 = str.substring(str.indexOf("否则")).replace("否则", "");
        
        
        boolean judge = judgeOperator(statement1, map);
        // System.out.println(judge);
        
        if( judge) {
            callFunction(statement2, map);
        }else {
            callFunction(statement3, map);
        }
    }

    @Test
    public void testTernary() {
        Map map = new HashMap();
        map.put("钱包", 10);
        ternaryOperator("如果 钱包 等于 十 则 看看 “钱太多了” 否则 看看 “我穷死了”", map);

    }

    /**
     * 判断语句,传入如果语句 例如:零 等于 零
     * @param str
     * @param map
     * @return 
     */
    public static boolean judgeOperator(String str, Map map) {

        String[] strArray = str.trim().split(" ");// 不去除左右空格,空格会被加入到分割数组
        String leftStr = strArray[0];
        String rightStr = strArray[2];
        String middle = strArray[1];
        int leftInt = 0;
        int rightInt = 0;

        if (map.get(leftStr) != null) {
            leftInt = map.get(leftStr);
        } else {
            leftInt = toNum(leftStr);
        }

        if (map.get(rightStr) != null) {
            rightInt = map.get(rightStr);
        } else {
            rightInt = toNum(rightStr);
        }

        switch (middle) {
        case "等于":
            return leftInt == rightInt;
        case "大于":
            return leftInt > rightInt;
        case "小于":
            return leftInt < rightInt;

        default:
            throw new IllegalArgumentException("judgeOperator没有对应的判断符号请输入(大于、等于、小于): " + middle);
        }
    }

    @Test
    public void testJudge() {
        Map map = new HashMap();
        map.put("钱包", 10);
        System.out.println(judgeOperator("零 等于 零", map));
    }

    /**
     * 汉字转化为数字
     * @return
     */
    public static int toNum(String str) {
        return numWords.indexOf(str);// -1不存在
    }
    
    /**
     * 数字转化为汉字
     * @param num
     * @return
     */
    public static String toChStr(int num) {
        
        return numWords.substring(num,num+1);
    }

    /**
     * 运算操作
     * @param str
     * @param map
     */
    public static void manipulateNum(String str, Map map) {
        String[] strArray = str.trim().split(" ");
        String varStr = strArray[0];
        String operator = strArray[1];
        String numStr = strArray[2];

        int num = 0;
        if (map.get(varStr) != null) {
            num = map.get(varStr);
        } else {
            throw new DemoException("变量:" + varStr + " 未定义");
        }

        switch (operator) {
        case "减少":
            num -= toNum(numStr);
            map.put(varStr, num);
            break;
        case "增加":
            num += toNum(numStr);
            map.put(varStr, num);
            break;
        default:
            throw new IllegalArgumentException("manipulateNum没有对应的判断符号请输入(增加、减少): " + operator);
        }
    }
    

    @Test
    public void testManipulate() {
        Map map = new HashMap();
        map.put("钱包", 10);
        manipulateNum("钱包 减少 四", map);
        System.out.println(map.get("钱包"));
    }
}

Exception类

public class DemoException extends RuntimeException {

    public DemoException() {
        super();
    }

    public DemoException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
        super(message, cause, enableSuppression, writableStackTrace);
    }

    public DemoException(String message, Throwable cause) {
        super(message, cause);
    }

    public DemoException(String message) {
        super(message);
    }

    public DemoException(Throwable cause) {
        super(cause);
    }

}

数据测试

测试数据1
第一次个人编程作业_第1张图片
测试数据2
第一次个人编程作业_第2张图片

编程记录

第一次提交的代码行数(包括文档注释和单元测试):260+
查资料+需求分析时间:2小时左右
第一次完成编码时间:4小时左右

思路

代码有三个类

  • DemoMain 存放主函数(处理传入的字符串,分割成行)
  • Utils 字符处理的工具类
  • DemoException (Demo的异常处理)

Utils类

  • callFunction 传入一行字符串,判断逻辑逻辑关键字并调用对应的方法
  • assignInt 整数赋值
  • printOut 输出字符串或者整数
  • ternaryOperator 三目操作
  • judgeOperator 判断语句(举例:零 等于 零)
  • toNum 把中文数字转化为数字
  • toChStr 把数字转化为中文数字
  • manipulateNum 增减运算

主要是根据功能的不同来分类,对于一些会被其他类经常用到的就单独抽取出来类如:toNum()和toChStr()和judgeOperator()

把toNum()和toChStr()划分出来有利于代码的迭代更新,目前仅实现了一位数字的运算,通过修改这两个方法就可以实现负数和多位数字的运算

public static String numWords = "零一二三四五六七八九十";
public static int toNum(String str) {
    return numWords.indexOf(str);
}

public static String toChStr(int num) {
    
    return numWords.substring(num,num+1);
}

代办

  • 负数和多位数字的运算
  • 完善异常处理

代码持续改进中,欢迎讨论交流

你可能感兴趣的:(第一次个人编程作业)