个人项目 - wordCount(Java实现)

wordCount

1. 项目相关要求

项目Github地址

这个项目要求写一个命令行程序 ,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。 作为实战项目,我完成的要求如下:

  • 基本功能
    • -c 统计字符数(支持√)
    • -w 统计单词数(支持√)
    • -l 统计行数(支持√)
  • 扩展功能
    • -s 递归处理目录下符合条件的文件(支持√)
    • -a 返回更复杂的数据——代码行 / 空行 / 注释行(支持√)
    • 支持各种文件的通配符(支持√)
  • 高级功能
    • 基本的Windows GUI 程序操作(支持√)
    • 支持通过图形界面选取文件(支持√)
    • 支持通过图形界面展现文件的信息(支持√)

 

2. 项目耗时预计(PSP)

实际耗时 PSP 表格在 blog 末尾给出

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划30
· Estimate· 估计这个任务需要多少时间30
Development开发550
· Analysis· 需求分析 (包括学习新技术)20
· Design Spec· 生成设计文档50
· Design Review· 设计复审 (和同事审核设计文档)30
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)30
· Design· 具体设计120
· Coding· 具体编码240
· Code Review· 代码复审30
· Test· 测试(自我测试,修改代码,提交修改)30
Reporting报告120
· Test Report· 测试报告60
· Size Measurement· 计算工作量30
· Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划30
合计700

 

3. 解题思路

刚拿到题目时以为是一个简单的统计单词的程序,但是当认真阅读项目的要求后,发现基础功能实现比较简单,但是对于扩展功能有点不知道如何下手。主要原因是对于项目要求中给出的代码行、注释行的解释十分疑惑。

空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。

代码行:本行包括多于一个字符的代码。

注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:

​ } //注释
在这种情况下,这一行属于注释行。

于是我决定先明确这些定义后再写代码,于是找了许多关于代码行和注释行的区别。最终发现最方便可以分辨这两者的工具是编辑器(或IDE),因为这些编辑器原生支持代码检查(当然记事本除外= =),可以区分出极端情况下究竟属于代码行还是注释行,譬如:

/** **/ int a = 3;

 

4. 设计实现过程

/view/MainView.java 负责显示 -x 参数打开的图形页面

/service/WordCount.java 负责处理命令行参数和代码计数

st=>start: 用户命令行输入
e=>end: 程序结束
cond=>condition: 是否含有 -x 参数

op_command=>operation: 命令行显示
op_view=>operation: 图形页面显示

st->cond
cond(yes)->op_view->e
cond(no)->op_command->e

 

5. 代码说明

以下是各参数实现的关键代码

  • 基本功能的实现
// /view/WrodCount.java
public void solution(File f) throws Exception {
    // 省略其他实现...
    while ((st = br.readLine()) != null) {
        text.append(st).append("\n");

        // 基本功能
        // 匹配字符数
        totalCharacters += st.length();

        // 匹配函数
        totalLines++;

        // 匹配单词
        int words = 0;
        Pattern pattern = Pattern.compile("\\w+");
        Matcher matcher = pattern.matcher(st);
        while (matcher.find()) {
            words++;
        }
        totalWords += words;
    }
    // 省略其它实现...
}
  • 扩展功能的实现
public void solution(File f) throws Exception {
    // 省略...
    while ((st = br.readLine()) != null) {
        // 省略...
        // 扩展功能
        if (!f.getAbsolutePath().endsWith(".txt")) {
            int indexOfFirstQuote = st.indexOf("\"");
            int indexOfSecondQuote = st.indexOf("\"", indexOfFirstQuote + 1);
            if (indexOfFirstQuote != -1 && indexOfSecondQuote != -1) {
                st = st.substring(0, indexOfFirstQuote) + st.substring(indexOfSecondQuote + 1, st.length() - 1);
            } else if (indexOfFirstQuote != -1 && indexOfSecondQuote == -1) {
                st = st.substring(0, indexOfFirstQuote);
            }

            if (hasMultiLineComment) {
                commentLine++;
                int indexOfMultiLineCommentEnd = st.indexOf("*/");
                if (indexOfMultiLineCommentEnd >= 0) {
                    //  /*
                    //  abc
                    // >*/
                    hasMultiLineComment = false;
                }
            } else {
                if (st.trim().length() <= 1) { // 判断空行
                    blankLine++;
                } else {
                    int indexOfDoubleSlash = st.indexOf("//");
                    int indexOfMultiLineCommentBegin = st.indexOf("/*");
                    if (indexOfDoubleSlash == -1 && indexOfMultiLineCommentBegin == -1) { // 不存在注释
                        codeLine++;
                    } else if (indexOfDoubleSlash != -1 && indexOfMultiLineCommentBegin == -1) { // 只存在单行注释
                        commentLine++;
                    } else if (indexOfDoubleSlash == -1 && indexOfMultiLineCommentBegin != -1) { // 只存在多行注释
                        commentLine++;
                        hasMultiLineComment = true;
                        if (st.indexOf("*/") > indexOfMultiLineCommentBegin) { // 多行注释结束于同一行
                            hasMultiLineComment = false;
                        }
                    } else if (indexOfDoubleSlash != -1 && indexOfMultiLineCommentBegin != -1) { // 存在单行注释和多行注释
                        if (indexOfDoubleSlash < indexOfMultiLineCommentBegin) { // 单行注释在前
                            commentLine++;
                        } else { // 多行注释在前
                            commentLine++;
                            hasMultiLineComment = true;
                            if (st.indexOf("*/") > indexOfMultiLineCommentBegin) { // 多行注释结束于同一行
                                hasMultiLineComment = false;
                            }
                        }
                    }
                }
            }
        }
    }
}

 

6. 测试运行

文件测试

  • 测试空文本:

1489095-20180912220954041-396496292.png

  • 测试只有一个字符的文件:

1489095-20180912221017382-287176982.png

1489095-20180912221052658-922335603.png

  • 测试只有一个单词的文件:

1489095-20180912221108119-2066506374.png

1489095-20180912221122578-912842908.png

  • 测试只有一行的文件:

1489095-20180912221143109-156852847.png

1489095-20180912221155129-521369569.png

  • 测试标准源文件:

1489095-20180912221207001-323838208.png

1489095-20180912221218038-1633473201.png

参数测试

  • -s 递归测试

1489095-20180912221233016-1780850163.png

  • 通配符?*支持

匹配所有扩展格式为 .txt 的文件

1489095-20180912221256491-1716265077.png

匹配所有test_?.*的所有文件

1489095-20180912221308186-129401588.png

  • -x 显示图形化界面

1489095-20180912221348847-2027092821.png

1489095-20180912221400657-1346605559.png

覆盖性测试

1489095-20180912221415078-2102865762.png

1489095-20180912221450437-1119281674.png

 

7. 实际花费时间(PSP)

PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning计划3050
· Estimate· 估计这个任务需要多少时间3050
Development开发550940
· Analysis· 需求分析 (包括学习新技术)2020
· Design Spec· 生成设计文档5030
· Design Review· 设计复审 (和同事审核设计文档)3050
· Coding Standard· 代码规范 (为目前的开发制定合适的规范)3010
· Design· 具体设计120150
· Coding· 具体编码240480
· Code Review· 代码复审3010
· Test· 测试(自我测试,修改代码,提交修改)3050
Reporting报告120140
· Test Report· 测试报告6050
· Size Measurement· 计算工作量3050
· Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划3040
合计7001130

 

8. 项目小结

根据上面给出的 PSP 表可以很明显看出,我花在计划还有报告的时间基本和估计的时间差不多,但是开发的时间(约 940 minutes)却远远超出一开始的预计(550 minutes)。这里说明两点,一点是自己对实际开发持乐观的态度,因此导致对实际项目开发的时间估计较短;还有一点是开发的时间过长。

仔细看开发中具体哪一项花费的时间最多,我发现我花了几乎两倍的具体编码时间,现在回顾起来发现自己在浪费了大量时间在扩展功能的开发上,主要原因是在动手写代码前没有彻底明确需求(特别是对扩展部分注释行定义的理解),导致在写代码过程中删删改改,越写感觉越多bug,然后再推倒重来...因此教训就是前期要花更多的时间在需求分析上,从而避免在开发过程中频繁地改动已经写过的代码,降低整个开发效率。

转载于:https://www.cnblogs.com/zkyyo/p/9637749.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值