第2周个人作业:WordCount

  • Github项目链接:

  https://github.com/JarrySmith/WC


  • PSP表格:

PSP2.1

PSP阶段

预估耗时

(分钟)

实际耗时

(分钟)

Planning

计划

 10

 5

· Estimate

· 估计这个任务需要多少时间

 10

 5

Development

开发

 825

 1100

· Analysis

· 需求分析 (包括学习新技术)

 200

 300

· Design Spec

· 生成设计文档

 30

 60

· Design Review

· 设计复审 (和同事审核设计文档)

 20

 30

· Coding Standard

· 代码规范 (为目前的开发制定合适的规范)

 15

 20

· Design

· 具体设计

 30

 30

· Coding

· 具体编码

 400

 450

· Code Review

· 代码复审

 30

 60

· Test

· 测试(自我测试,修改代码,提交修改)

 100

 150

Reporting

报告

 60

 70

· Test Report

· 测试报告

 30

 40

· Size Measurement

· 计算工作量

 10

 10

· Postmortem & Process Improvement Plan

· 事后总结, 并提出过程改进计划

 20

 20

 

合计

 890

 1175


  • 解题思路

          首先很明显,分为包含-s的目录寻找以及非目录寻找的其他命令,我采取的是遍历命令行参数,获取需要进行的操作,如计算单词,计算行数等等.然后有些选项如-o,-e则在第一遍遍历的时候进行检测,其后面是不是有指定文本,如果指定了,那么把输出指向该文本,如果没有指定,那么就直接报错,不需要执行接下来的命令,加快了速度.

     说到文本,那就有关于文本读写方面的内容,我参考了博客【1】中的文本操作。递归遍历参考了博客【2】,获取当前路径参考了博客【3】

   再统计字符,单词,行数比较简单,不多说.值得注意的是-s和-a。-s需要指定特定目录下的指定类型的文本,这里牵涉到关于文本类型的过滤,是默认当前目录还是命令行传入的目录.*.type可以单独存在也可接在目录后面,这都是需要在遍历的时候去解析的。至于-a,自然是关于注释行,空行,代码行的判断了,我的实现是,先判断是不是空行,再判断是不是注释行,如果都不是,那就是代码行.其中有一种是多行注释的最后加上了代码,算是代码行,关于这个,在多行结束判断中,加入一个判断最后一个字符是否为'/'。

         对于每个选项的细节实现上不做过多的展开.稍后的代码展现可以再看到具体的.


  •   程序设计实现过程

    由于工程量不大,所以把所有函数写在一个类里静态调用.共十一个函数.

  countchars、countlines、count_word分别统计字符数,行数,单词数
  is_emptyline、is_expline 用来判断是否为空行,注释行,是被countdetail调用
  get_stopword、readToString、saveresult都是辅助函数,功能为获取停用词表的词,将读入的文本转化为字符串,保存统计结果

WC、traversepath为两个关键的入口函数,根据是否包含-s分为两个部分去进行统计工作


  • 代码说明

   1.WC函数,关键入口函数,解析命令行参数表.在第一遍遍历进行了错误判断,利用param是否包含-s进行分支选择,分别处理

public static void WC(String[] args) {
        int words = 0;
        int lines = 0;
        int chars = 0;
        int[] detail = new int[3];

        CharSequence save = ".txt";
        String filepath = null;

        boolean checked_file = false;
        for (int i = 0; i < args.length; i++) {
            if (args[i].contains(".txt")) continue;
            //停用词的文件判断
            if (args[i].equals("-e")) {
                if (i == args.length - 1) {
                    System.out.println("没有指定停用词文本");
                    err = true;
                } else if (!(args[i + 1].contains(save))) System.out.println("停用词文本需紧跟在-e后");
                else stop_path = args[i + 1];
            }
            //判断是否函数输出文本
            if (args[i].equals("-o")) {
                if (i == args.length - 1) {
                    System.out.println("没有指定输出结果文本");
                    err = true;
                } else if (!(args[i + 1].contains(save))) System.out.println("result.txt需紧跟在-o后");
                else save_path = args[i + 1];
            }
            string_args.append(args[i]);
        }
        param = string_args.toString();
        if (!err) {
            if (param.contains("-s")) {
                //默认path为当前目录
                String path =  System.getProperty("user.dir");
                for (int i = args.length - 1; i > 0; i--) {
                    if (args[i].contains("*.")) {
                        //获取指定文件类型和指定目录
                        if(args[i].length()>15) path= args[i].split("\.")[0].replace("*","");
                        filetype = "." + args[i].split("\.")[1];
                    }
                }
                //开始遍历目录
                traversepath(path);
            } else {
                //错误判断
                for (int i = 0; i < args.length; i++) {
                    if (args[i].contains("*.")){err=true;System.out.println("只有输入-s才能进行全目录遍历规定文件");}
                    if (args[i].contains(".")) {
                        filepath = args[i];
                        break;
                    }
                }
            if(!err)
            {
                //及非遍历统计
            if (param.contains("-c")) chars = countchars(filepath);
            if (param.contains("-l")) lines = countlines(filepath);
            if (param.contains("-w")) words = count_word(filepath);
            try {
                if (param.contains("-a")) detail = countdetail(filepath);
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
        }
    }
        saveresult(words,lines,chars,detail,filepath);
        }

    2.traversepath函数 根据特定的文本类型,遍历指定目录及其子目录,分别进行统计工作然后保存

public static void traversepath(String path) {
        File file = new File(path);
        if (file.exists()) {
            File[] files = file.listFiles();
            //如果是个空文件夹
            if (files.length == 0) {
                return;
            } else {
                for (File file2 : files) {
                    if (file2.isDirectory()) {
                        //遍历子目录
                        traversepath(file2.getAbsolutePath());
                    } else {
                        String filename = file2.getName();
                        if (filename.endsWith(filetype)) {
                            String filepath = path + '\' + filename;
                            int words = 0;
                            int lines = 0;
                            int chars = 0;
                            int[] detail = new int[3];
                            //根据参数进行统计
                            try {
                                if (null == param) break;
                                if (param.contains("-a")) detail = countdetail(filepath);
                                if (param.contains("-w")) words = count_word(filepath);
                                if (param.contains("-c")) chars = countchars(filepath);
                                if (param.contains("-l")) lines = countlines(filepath);
                                saveresult(words, lines, chars, detail, filename);
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
        }
    }

  • 测试设计过程

如何设计?覆盖所有判断路径,分支

  关于命令行参数不完整和不正确 会导致程序高风险

  测试用例设计如下:

  1. wc.exe -l a.c
  2. wc.exe -w a.c
  3. wc.exe -c a.c
  4. wc.exe -a a.c
  5. wc.exe -l a.c -o result.txt
  6. wc.exe -l a.c -o
  7. wc.exe -w a.c -e stoplist.txt
  8. wc.exe -w a.c -e
  9. wc.exe -s -a *.c
  10. wc.exe -s -a
  11. wc.exe -s -a *.java

  测试脚本代码如下:

wc.exe -l a.c
wc.exe -w a.c
wc.exe -c a.c
wc.exe -a a.c
wc.exe -l a.c -o result.txt
wc.exe -l a.c -o
wc.exe -w a.c -e stoplist.txt
wc.exe -w a.c -e
wc.exe -s -a *.c
wc.exe -s -a
wc.exe -s -a *.java
pause>nul


  • 参考文献链接

  【1】https://www.cnblogs.com/oracleblogs/p/6591656.html

  【2】https://www.cnblogs.com/azhqiang/p/4596793.html

  【3】https://www.cnblogs.com/franson-2016/p/5728280.html

 

原文地址:https://www.cnblogs.com/Jarry-smith/p/8597560.html