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;
        }
    

    五、测试

  • 相关阅读:
    HDU 4348 To the moon(可持久化线段树)
    HDU 5875 Function 大连网络赛 线段树
    HDU 5877 2016大连网络赛 Weak Pair(树状数组,线段树,动态开点,启发式合并,可持久化线段树)
    HDU 5876 大连网络赛 Sparse Graph
    HDU 5701 中位数计数 百度之星初赛
    CodeForces 708B Recover the String
    Java实现 蓝桥杯 算法提高 套正方形(暴力)
    ASP.NET生成验证码
    ASP.NET生成验证码
    ASP.NET生成验证码
  • 原文地址:https://www.cnblogs.com/caoe666/p/14638621.html
Copyright © 2011-2022 走看看