软测第二周作业WordCount

本文档详细记录了PSP2.1个人软件过程的实际应用情况,包括任务的时间估计与实际消耗对比、代码实现的具体思路及关键部分的源代码展示。此外,还介绍了项目的测试流程及作者的个人体会。

一、Github地址:

https://github.com/duwei1996/wc

二、PSP2.1表格

PSP2.1

PSP阶段

预估耗时

(分钟)

实际耗时

(分钟)

Planning

计划

3030

· Estimate

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

3030

Development

开发

540900

· Analysis

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

60120

· Design Spec

· 生成设计文档

00

· Design Review

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

00

· Coding Standard

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

60120

· Design

· 具体设计

6060

· Coding

· 具体编码

240360

· Code Review

· 代码复审

60120

· Test

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

6060

Reporting

报告

90120

· Test Report

· 测试报告

3045

· Size Measurement

· 计算工作量

3030

· Postmortem & Process Improvement Plan

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

3045
 

合计

7001050

三、设计思路

1.程序设计两个主要方法baseFunction()和extendFunction(),分别用于实现基本功能和扩展功能

2.设计辅助方法如countChar()、countLine()等供上面两个方法调用

3.根据接收的命令参数,判断执行相应的操作

四、主要代码

1.main函数

  从输入参数获取要处理的文件, 并对文件做基本功能和扩展功能的处理

public static void main(String[] args) throws Exception{ 
    File file = new File(args[args.length-1]);     
    baseFunction(args,file);
    extendFunction(args,file); 
}

 

2.baseFunction函数和baseCount函数

  调用baseCount方法,根据参数,输出相应结果

public static void baseFunction(String[] strings, File file)throws IOException{
        if (file == null || !file.exists())
            throw new FileNotFoundException(file + ",文件不存在!");

        baseCount(file);

        List<String> list = Arrays.asList(strings);

        if (list.contains("-c")){
            //countChar()
            System.out.println(file.getName() + "," + result1);
        }
        if (list.contains("-w")&& !list.contains("-e")){
            //countWord()
            System.out.println(file.getName() + "," + result2);
        }
        if (list.contains("-l")){
            //counLine()
            System.out.println(file.getName() + "," + result3);
        }
        if (list.contains("-o")){
            String content = new String(file.getName() + "\r\n" + result1 + "\r\n" + result2 + "\r\n" + result3);
            Path outPath = Paths.get("output.txt");
            File output = new File(outPath.toString());
            Files.write(outPath,content.getBytes());
        }

    }

  baseCount方法用于读取文件内容,并计算字符、单词和行数

 public static void baseCount(File file) throws IOException{
        BufferedReader br = helper(file);
        String s = null;
        while ((s = br.readLine()) != null){
            s = br.readLine();
            countChar(s);
            countWord(s);
            countLine(s);
        }
    }

 

3.extendFunction函数和extendCount函数

  调用baseCount方法,根据参数,输出相应结果  

public static void extendFunction(String[] strings,File file)throws IOException{

        extendCount(file);

        List<String> list = Arrays.asList(strings);
        if (list.contains("-s")){
            //recFile(file);
        }
        if (list.contains("-a")){
            System.out.println(file.getName() +",代码行 / 空行 / 注释行:" + codeLineNum + "/" + blankLineNum + "/" + annotationLineNum);
        }
        if (list.contains("-w")&&list.contains("-e")){
            baseCount(file);
            String s1 = list.get(list.indexOf("-w")+1);
            String s2 = list.get(list.indexOf("-e")+1);
            File file1 = new File(s1);
            File file2 = new File(s2);
            int sameNum = stopList(file1,file2);
            System.out.println(file.getName() +",单词数:" + (wordNum - sameNum));
        }
    }

  extendCount方法

public static void extendCount(File file) throws IOException{
        exCountLine(file);
        recFile(file);
    }

  exCountLine方法

public static void exCountLine(File file) throws IOException {
        if (file == null || !file.exists())
            throw new FileNotFoundException(file + ",文件不存在!");

        //fileCount ++;   // 文件数累加

        if (file.isDirectory()) {
            recFile(file);
        } else {
            BufferedReader bufr = null;
            try {
                // 将指定路径的文件与字符流绑定
                bufr = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
            } catch (FileNotFoundException e) {
                throw new FileNotFoundException(file + ",文件不存在!" + e);
            }

            // 定义匹配每一行的正则匹配器
            Pattern annotationLinePattern = Pattern.compile("((//)|(/\\*+)|((^\\s)*\\*)|((^\\s)*\\*+/))+",
                    Pattern.MULTILINE + Pattern.DOTALL);    // 注释匹配器(匹配单行、多行、文档注释)

            Pattern blankLinePattern = Pattern.compile("^\\s*$");    // 空白行匹配器(匹配回车、tab键、空格)

            Pattern codeLinePattern = Pattern.compile("(?!import|package).+;\\s*(((//)|(/\\*+)).*)*",
                    Pattern.MULTILINE + Pattern.DOTALL); // 代码行匹配器(以分号结束为一行有效语句,但不包括import和package语句)

            // 遍历文件中的每一行,并根据正则匹配的结果记录每一行匹配的结果
            String line = null;
            try {
                while ((line = bufr.readLine()) != null) {
                    if (annotationLinePattern.matcher(line).find()) {
                        annotationLineNum++;
                    }

                    if (blankLinePattern.matcher(line).find()) {
                        blankLineNum++;
                    }

                    if (codeLinePattern.matcher(line).matches()) {
                        codeLineNum++;
                    }
                }

            } catch (IOException e) {
                throw new RuntimeException("读取文件失败!" + e);
            } finally {
                try {
                    bufr.close();    // 关闭文件输入流并释放系统资源
                } catch (IOException e) {
                    throw new RuntimeException("关闭文件输入流失败!");
                }
            }
        }
    }

  recFile函数,实现递归处理文件夹

public static void  recFile(File file) throws IOException{
        File[] files = file.listFiles(new FileFilter() {
            public boolean accept(File pathname) {
                return pathname.getName().endsWith(".c") || pathname.isDirectory();
            }
        });

        for (File target : files) {
            extendCount(target);
        }

    }

  stopList函数,实现禁用单词计数;

public static int stopList(File file1,File file2) throws IOException{
        String[] strings1 = word(file1);
        String[] strings2 = word(file2);
        return same(strings1,strings2);
    }
    public static String[] word(File file) throws IOException{
        BufferedReader br = helper(file);
        String s = null;
        String[] content = null;
        while ((s=br.readLine())!=null){
            s = br.readLine();
            String a = ",";
            s.replaceAll(a," ");
            content = s.split(" ");
        }
        return content;
    }
    public static int same(String[] a,String[] b){
        ArrayList<String> same = new ArrayList<String>();
        ArrayList<String> temp = new ArrayList<String>();

        for (int i = 0; i < a.length; i++) {
            temp.add(a[i]);   //把数组a中的元素放到Set中,可以去除重复的元素
        }

        for (int j = 0; j < b.length; j++) {
            //把数组b中的元素添加到temp中
            //如果temp中已存在相同的元素,则temp.add(b[j])返回false
            if(!temp.add(b[j]))
                same.add(b[j]);
        }
        return same.size();
    }

 

五、测试

1.基本功能

wc.exe -c file.c     //返回文件 file.c 的字符数
wc.exe -w file.c     //返回文件 file.c 的单词总数
wc.exe -l file.c     //返回文件 file.c 的总行数
wc.exe -o outputFile.txt     //将结果输出到指定文件outputFile.txt

测试文本

命令与结果

 

2.扩展功能

wc.exe -s            //递归处理目录下符合条件的文件
wc.exe -a file.c     //返回更复杂的数据(代码行 / 空行 / 注释行)
wc.exe -e stopList.txt  // 停用词表,统计文件单词总数时,不统计该表中的单词

禁用列表

命令与结果

     

     

注:另外两个功能尚未实现

六、体会

  通过编程,更深地体会到需求设计的重要性;通过测试,更加了解需求与产品之间的差别,以及测试的必要性和重要性。

 

七、参考文献

 http://www.cnblogs.com/ningjing-zhiyuan/p/8563562.html

 

 

 

转载于:https://www.cnblogs.com/duwei1996/p/8613783.html

(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值