zoukankan      html  css  js  c++  java
  • 202103226-1 编程作业

    这个作业属于哪个课程 https://edu.cnblogs.com/campus/zswxy/computer-science-class4-2018
    这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/computer-science-class4-2018/homework/11880
    这个作业的目标 写一个能统计出文件中出现最多次数的词
    其他参考文献 构建之法,CSDN,java开发实战经典

    二、PSP表格

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 25 40
    • Estimate • 估计这个任务需要多少时间 1100 1200
    Development 开发 300 400
    • Analysis • 需求分析 (包括学习新技术) 200 350
    • Design Spec • 生成设计文档 30 30
    • Design Review • 设计复审 30 30
    • Coding Standard • 代码规范 (为目前的开发制定合适的规范) 10 10
    • Design • 具体设计 30 40
    • Coding • 具体编码 180 250
    • Code Review • 代码复审 60 80
    • Test • 测试(自我测试,修改代码,提交修改) 100 100
    Reporting 报告 100 120
    • Test Repor • 测试报告 10 10
    • Size Measurement • 计算工作量 10 10
    • Postmortem & Process Improvement Plan • 事后总结, 并提出过程改进计划 30 30
    合计 1090 1460

    三、gitee地址

    https://gitee.com/the-first-semester-of-2021/project-java#project-java

    四、需求

    实现一个命令行程序,不妨称之为WordCount。
    1、实现基本需求
    假设有一个软件每隔一小段时间会记录一次用户的搜索记录,记录为英文。

    输入文件和输出文件以命令行参数传入。例如我们在命令行窗口(cmd)中输入:

    //C语言类
    WordCount.exe input.txt output.txt

    //Java语言
    java WordCount input.txt output.txt
    则会统计input.txt中的以下几个指标

    统计文件的字符数(对应输出第一行):

    只需要统计Ascii码,汉字不需考虑
    空格,水平制表符,换行符,均算字符
    统计文件的单词总数(对应输出第二行),单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。

    英文字母: A-Z,a-z
    字母数字符号:A-Z, a-z,0-9
    分割符:空格,非字母数字符号
    例:file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词
    统计文件的有效行数(对应输出第三行):任何包含非空白字符的行,都需要统计。

    统计文件中各单词的出现次数(对应输出接下来10行),最终只输出频率最高的10个。

    频率相同的单词,优先输出字典序靠前的单词。

    例如,windows95,windows98和windows2000同时出现时,则先输出windows2000

    输出的单词统一为小写格式

    然后将统计结果输出到output.txt,输出的格式如下;其中word1和word2 对应具体的单词,number为统计出的个数;换行使用' ',编码统一使用UTF-8。

    characters: number
    words: number
    lines: number
    word1: number
    word2: number
    ...
    2、接口封装
    如果现在我们要把这个功能放到不同的环境中去(例如,命令行,Windows图形界面程序,网页程序,手机App),就会碰到困难:代码散落在各个函数中,很难剥离出来作为一个独立的模块运行以满足不同的需求。

    这些代码的种类不同,混杂在一起对于后期的维护扩展很不友好,所以它们的组织结构就需要精心的整理和优化。

    我们希望把基本功能里的:

    统计字符数
    统计单词数
    统计最多的10个单词及其词频
    这三个功能独立出来,成为一个独立的模块(class library, DLL, 或其它),这样的话,命令行和GUI的程序都能使用同一份代码。为了方便起见,我们称之为计算核心"Core模块",这个模块至少可以在几个地方使用:

    命令行测试程序使用
    在单元测试框架下使用
    与数据可视化部分结合使用
    把计算核心在单元测试框架中做过完备的测试后,我们就可以在算法层级保证了这个模块的正确性。
    但我们知道软件并非只有计算核心,实际的软件是交付给最终用户的软件,除了计算核心外,还需要有一定的界面和必要的辅助功能。

    这个Core模块和使用它的其他模块之间则要通过一定的API来交流。
    API应该怎么设计呢?
    为了方便起见,我们可以从下面的最简单的接口开始(仅举例,你的代码里可能没有这个函数):

    int countChar(File *file)
    这个函数表示输出一个文件指针,返回这个文件的字符数。
    假设我们用Core封装了这个接口,那么我们的测试程序可以是这样:

    File *in = fopen("input.txt","r");
    int count = 100;
    Assert(countChar(in) == count);
    当然,这样的测试程序并不充分,希望大家测试时不要像这样偷懒。

    3、单元测试和性能分析
    请根据自己以往积累的测试经验,在编码完成之后,提交产品之前,设计测试用例,并编写单元测试,对自己的项目进行测试。首先,至少应采用白盒测试用例设计方法来设计测试用例,其他测试方法不限。其次,要设计至少10个测试用例,确保你的程序能够正确处理各种情况。最后,结合测试评估的要求,对自己的测试设计进行评价,这些测试用例能满足该程序测试的要求吗?

    另一个重要的措施是要把单元测试自动化,这样每个人都能很容易地运行它,并且可以使单元测试每天都运行。每个人都可以随时在自己的机器上运行。团队一般是在每日构建中运行单元测试的,这样每个单元测试的错误就能及时被发现并得到修改。

    请阅读邹欣老师的博客,编写程序的单元测试:关于单元测试和回归测试
    c++可以使用vs2017。对于博客任务中的单元测试、性能分析(Studio Profiling Tools),vs2017有相应的功能。
    java可以使用idea。也可以自行查找使用其他工具。
    package statistics;

    import java.io.;
    import java.util.
    ;
    /**题目:用java,统计txt文件中每个文字或者字母出现的次数,并由大到小排列,
    并显示每个文字或者字母出现的次数
    思路:
    1.定义字符读取(缓冲)流
    2.循环读取文件里的字符,用一个String类型变量接收(newValue)
    3.把newValue变成字符数组 char[] ch = newValue.toCharArray();
    4.遍历ch 将ch中所有的字符存入一个Map集合中(TreeSet),键对应字符,值对应字符出现的次数
    5.遍历打印map集合中的键和值,也就是字符出现的次数

    package statistics;
    
    import java.io.BufferedReader;
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    import java.util.*;
     
    public class FileWordCount {
        public static void main(String[] args) {
            try {
                BufferedReader br = new BufferedReader(new FileReader("D:\test.txt"));
                String s;
                StringBuffer sb = new StringBuffer();
                while ((s = br.readLine()) != null) {
                    sb.append(s);
                }
                Map<String,Integer> map = new HashMap<String, Integer>();
                StringTokenizer st = new StringTokenizer(sb.toString(),",.! 
    ");
                while (st.hasMoreTokens()) {
                    String letter = st.nextToken();
                    int count;
                    if (map.get(letter) == null) {
                        count = 1;
                    } else {
                        count = map.get(letter).intValue() + 1;
                    }
                    map.put(letter,count);
                }
                Set<WordEntity> set = new TreeSet<WordEntity>();
                for (String key : map.keySet()) {
                    set.add(new WordEntity(key,map.get(key)));
                }
                // 自己拼接字符串,输出我们想要的字符串格式
                System.out.println("输出形式一:");
                for (Iterator<WordEntity> it = set.iterator(); it.hasNext(); ) {
                    WordEntity w = it.next();
                    System.out.println("单词:" + w.getKey() + " 出现的次数为: " + w.getCount());
                }
                // 直接打印 WordEntity 对象,实现我们想要的输出效果,只需在WordEntity类中重写toString()方法
                System.out.println("输出形式二:");
                for (Iterator<WordEntity> it = set.iterator(); it.hasNext(); ) {
                    WordEntity w = it.next();
                    System.out.println(w);
                }
                // 我们可以控制只输出前三名来
                System.out.println("输出形式三:");
                int count = 1;
                for (Iterator<WordEntity> it = set.iterator(); it.hasNext(); ) {
                    WordEntity w = it.next();
                    System.out.println("第" + count + "名为单词:" + w.getKey() + " 出现的次数为: "
                            + w.getCount());
                    if (count == 3)// 当输出3个后跳出循环
                        break;
                    count++;
                }
            } catch (FileNotFoundException e) {
                System.out.println("文件未找到~!");
            } catch (IOException e) {
                System.out.println("文件读异常~!");
            }
        }
    }
    
    package statistics;
    public class WordEntity implements Comparable<WordEntity> {
        private String key;
        private Integer count;
        public WordEntity (String key, Integer count) {
            this.key = key;
            this.count = count;
        }
        public int compareTo(WordEntity o) {
            int cmp = count.intValue() - o.count.intValue();
            return (cmp == 0 ? key.compareTo(o.key) : -cmp);
            //只需在这儿加一个负号就可以决定是升序还是降序排列  -cmp降序排列,cmp升序排列
            //因为TreeSet会调用WorkForMap的compareTo方法来决定自己的排序
        }
     
        @Override
        public String toString() {
            return key + " 出现的次数为:" + count;
        }
     
        public String getKey() {
            return key;
        }
    

    五、测试

  • 相关阅读:
    pyspider安装
    阿里云服务器数据盘扩容
    笔记之Python网络数据采集
    Nginx如何隐藏index.html
    使用fiddler手机抓包
    Git基本常用命令
    27 和为S的两个数字
    26 函数形参值回传问题——C++解决多个return的一般方法
    25 面向对象设计实例——基于PCL点云库的通用工具开发
    23 Pro/E二次开发中的问题记录
  • 原文地址:https://www.cnblogs.com/caoe666/p/14638621.html
Copyright © 2011-2022 走看看