ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

2021秋软工实践第一次个人编程作业

2021-09-20 19:33:38  阅读:196  来源: 互联网

标签:tmp keyWord 编程 秋软工 else switch 2021 line tmp2


这个作业属于哪个课程构建之法-2021秋-福州大学软件工程
这个作业要求在哪里2021秋软工实践第一次个人编程作业
这个作业的目标实现一个程序功能,它可以对读入的C或C++代码文件进行不同等级的关键字提取
学号031902641

一、 PSP 表格

PSP Stages预估耗时(小时)完成时间(小时)
计划0.50.5
时间预估0.10.2
开发--
需求分析1.52
生成设计文档--
设计复审0.40.3
代码规范11
具体设计23
具体编码1520
代码复审0.20.25
测试12
报告22.5
测试报告0.50.5
计算工作量0.10.1
总结与提高0.51
总计24.833.35

二、解题思路描述

题目要求:

实现一个程序功能,它可以对读入的C或C++代码文件进行不同等级的关键字提取。

  • 基础要求:输出关键字统计信息

  • 进阶要求:输出有几组switch case结构,同时输出每组对应的case个数

  • 拔高要求:输出有几组if else结构

  • 终极要求:输出有几组if,else if,else结构

在完成更高要求的情况前,需完成前置的要求。

解题思路

基本步骤

1. 选择用 Java 编写本次作业

2. 从键盘读入文件路径和等级要求,要使用 Scanner 类进行接收

3. 读入 C 或 C++ 代码,那么就要使用文件流进行读操作,并且把读入的内容存储到字符串中

4. 要统计关键词,要进行关键词匹配和统计,可以使用字符串的方法 equals() 进行比较

5. 统计 switch case 结构数,以及对每组对应的 case 个数进行统计

6. 统计 if-else 和 if-else if-else 结构,产生的嵌套匹配可能需要用到数据结构的知识

7. 根据输入的等级要求调用不同的方法,最终结果输出在控制台

思考&疑惑

基本步骤理清之后,整个作业的结构已经差不多搭建好

虽然结构好像很清晰,但是心中还是很多对细节的疑惑,尤其是对步骤 5 和 6,总觉得很复杂。

疑惑一:c 或者 cpp 文件的内容直接全部拼接成一个字符串会不会超过 String 能存的最大长度?分多个字符串存?String 类型数组?

解答:选用 StringBuilder 的 append() 方法,具体可参考
String、StringBuffer与StringBuilder之间区别

疑惑二:如何计算每个 switch 块里的 case 个数? 用 default 来判断当前代码块结束?那要是没 default 怎么办?

解答:咨询带佬之后决定使用括号匹配。每个 switch 后的作用域都是由一个 {} 围起来的,把 switch 后的 { 入栈,遇到 } 出栈,栈空之时代表当前 switch 作用域结束。

疑惑三:如何区别 if-else 和 if-else if-else?

解答:使用栈进行匹配和区分,将 if 和 else if 都压栈,遇到 else 出栈,如果栈顶是 if ,则为 if-else 结构;如果栈顶是 else if,则为if -else if-else 结构。

疑惑四:单元测试和性能测试是什么,使用什么工具?

解答:单元测试使用 ,具体参考Java单元测试初体验
性能测试工具用的是JProfilerIntelliJ IDEA集成JProfiler,入门教程

三、代码说明

完整代码在keyWords

1. 对文本进行预处理,去掉注释和字符串,防止关键字误判(基本思路都在注释里)
        /*
        * 对文本进行预处理
        * */
        while(line != null) {
            // 去掉字符串
            char quotationMark = '"';
            if(line.indexOf(quotationMark) != -1) {
                CharBetween charBetween = new CharBetween(quotationMark, line);
                line = charBetween.getBetweenString();
            }

            // 去掉单行注释
            String noteInline = "//";
            if(line.contains(noteInline)) {
                int tmp = line.indexOf(noteInline);
                if(tmp == 0) {
                    line = bufferedReader.readLine(); // 读取下一行
                    continue;
                }
                else  line = line.substring(0, tmp);
            }
            // 拼接字符串
            fileContent.append(line);
            line = bufferedReader.readLine(); // 读取下一行
        }
        // 去掉多行注释
        fileContent = new TrimNote().trimNote(fileContent);

去除多行注释的方法

    public StringBuilder trimNote (StringBuilder string) {
        String noteBlockStart = "/*";
        String noteBlockEnd = "*/";
        
        while(string.indexOf("/*") != -1) {
            int startIndex = string.indexOf(noteBlockStart);
            int endIndex = string.indexOf(noteBlockEnd, startIndex + 1);

            if(startIndex < 0 || endIndex < 0) break;
            string.replace(startIndex, endIndex + 2, "");
        }
        return string;
    }


2. 统计关键字和统计每个 switch 对应的 case 数量

2.1 流程图

在这里插入图片描述

2.2 代码

for (String keyWord : keyWords) {
            String tmp = fileContent.toString();
            count = 0;
            caseCountTmp = 0;
            int flag = 0;
            while (tmp.contains(keyWord)) {
                // 判断关键字是否包含在变量中 如果有这样的变量则删去
                char pre = tmp.charAt(tmp.indexOf(keyWord) - 1);
                char after = tmp.charAt(tmp.indexOf(keyWord) + keyWord.length());
                if (judgeItemInString(pre) || judgeItemInString(after)) {}
                else {
                    count++;
                    if (keyWord.equals("case") && flag == 0) {
                        String tmp2 = tmp;
                        for(int i = tmp2.indexOf("switch"); i < tmp2.length() && tmp2.contains("switch"); i++) {
                            if(tmp2.charAt(i) == '{') {
                                bracket.push("{");
                            }
                            if(tmp2.charAt(i) == '}') {
                                bracket.pop();
                                if(bracket.size() == 0) {
                                    caseCount.add(caseCountTmp);
                                    caseCountTmp = 0;
                                    tmp2 = tmp2.substring(i + 1);
                                    i = tmp2.indexOf("switch");
                                }
                            }
                            if(tmp2.contains("switch")) {
                                if(tmp2.charAt(i) == 'c' && tmp2.charAt(i+1) == 'a' && tmp2.charAt(i+2) == 's' 
                                        && tmp2.charAt(i+3) == 'e') {
                                    caseCountTmp++;
                                }
                            }
                        }
                        flag = 1;
                    }
                }
                tmp = tmp.substring(tmp.indexOf(keyWord) + keyWord.length());
            }
            map.put(keyWord, count);
        }


3. 统计和区分 if-else 和 if-else if-else

3.1 思路
将 if 和 else if 都压栈,遇到 else 出栈,此时进行计数。如果栈顶是 if ,则为 if-else 结构;如果栈顶是 else if,则为if -else if-else 结构。

3.2 代码

    public void statisticsKeyWord(int level) {
        int ifElseCount = 0;
        int ifElseIfElseCount = 0;
        for(int i = 0; i < this.keyWordTmp.size(); i++) {
            if(this.keyWordTmp.get(i).equals("1")) this.keyWord.push("1");
            if(this.keyWordTmp.get(i).equals("2")) {
                this.keyWord.push("2");
            }
            if(this.keyWordTmp.get(i).equals("3")) {
                if(this.keyWord.peek().equals("2")) {
                    while(this.keyWord.peek().equals("2")) this.keyWord.pop();
                    ifElseIfElseCount++;
                } else
                    ifElseCount++;
                this.keyWord.pop();
            }
        }

        if(level == 3) {
            System.out.print("if-else num: " + ifElseCount);
        }
        if(level == 4) {
            System.out.println("if-else num: " + ifElseCount);
            System.out.println("if-elseif-else num: " + ifElseIfElseCount);
        }
    }


四、迭代过程

看 commit 的时间图基本可以看出迭代的过程

搭好基本的功能模块,实现输入 -> 实现文本预处理 -> 完成 level1 -> 完成 level2 -> 完成 level3 -> 完成 level4 -> 复盘、修复 bug

在这里插入图片描述

五、单元测试和性能测试

5.1 单元测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mFt3D45L-1632136984585)(https://img-community.csdnimg.cn/images/3247f67242104f5ea268a8d252c6fa90.png "=500 #left")]

5.2 性能测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mdt6vJgA-1632136984587)(https://img-community.csdnimg.cn/images/333b2ab7631b4c80b79184f67b3bf016.png "=500 #left")]

六、总结

本次作业感觉对我这个初试 Java 的人来说还是有一定难度。但最难的感觉还是解题思路,到博文写完的这一刻 if-else 和 if-else if-else 匹配仍存在bug,如果有 if 没有 else 进行匹配的话答案就是错误的。尤其是性能测试和单元测试,看了一些博文还是挺懵的,仅仅是跟着示例当了一回机器人,更不要说性能优化了。希望在接下来的作业中能继续锻炼到我使用 Java 和数据结构知识解决实际问题的能力,据说 switch 嵌套很可怕,接下来除了解决上面的 bug 以外还会思考 switch 嵌套的问题,继续维护这份代码。

标签:tmp,keyWord,编程,秋软工,else,switch,2021,line,tmp2
来源: https://blog.csdn.net/joi119/article/details/120394385

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有