201671010412 郭佳 实验二 软件工程个人项目

本次软件工程个人项目要求用Java实现英文文本词频统计软件。程序需实现读入文件、指定单词词频统计、高频词统计等功能。通过四个类实现模块化设计,包含主函数和三个功能类。经测试运行,验证了各功能的正确性,同时总结了模块化设计的优势。
作业要求:《实验二 软件工程个人项目》
本项目Github的仓库主页

1. 需求分析

本次实验要求使用JAVA编程语言,独立完成一个英文文本词频统计的软件开发。
该程序要求实现:

  • 要求能够读入任意英文文本文件,该文件中英文词数大于等于一个;
  • 要能够容纳英文原版《哈利波特》10万词以上的文章;
  • 要有指定单词的词频统计功能,即用户可输入从该文本中想要查找词频的一个或任意多个英文单词,运行程序的统计功能可显示对应单词在文本中出现的次数和柱状图;
  • 高频单词统计功能,即用户共键盘输入高频词输出个数k,运行程序统计功能,可按文本中词频数降序显示前k个单词的词频及单词;
  • 统计该文本所有单词数量及词频数,并能将单词及词频数按字典顺序输出到文件result.txt

2. 功能设计

根据需求分析中提到的内容,本程序中设计以下几个功能:

  • 统计文件中所有单词及其词频数,且输出到指定文件;
  • 统计指定单词在文件中出现的次数;
  • 输出前K个高频词的个数及其柱状图;

程序流程图:
程序流程图

3. 设计实现

本程序包含四个类,包括一个主函数Main.java和三个功能类,分别是Count1.java,Count1.java,Count1.java主程序主要是用来控制程序的整个流程,用户输入不同的功能选项,来调用这三个功能。三个类的功能分别是:

  • Count1.java:该类是用来实现对指定文件中所有单词及其词频进行统计功能的,统计完成后并将统计结果输出到指定文件中。
  • Count2.java:该类是用来实现用户从键盘输入任意一个单词,查询并统计该单词在文件中出现的次数功能的,若查询的该单词不存在则显示提示信息。
  • Count3.java:该类是用来实现统计用户指定任意个数的高频词频及其柱状图功能的。

1614524-20190317224628282-903557883.png

4. 测试运行

  • 本程序主界面显示如下:

    1614524-20190317224839079-239410299.png

  • 功能选项1测试:

    选择选项1,显示文件中所有单词个数及其词频统计结果,并将结果输出到指定文件中。
    1614524-20190317224903042-642700179.png
    1614524-20190317224914743-972897978.png

  • 功能选项2测试:

    用户任意输入想要在文件中查询的单词,查询并显示结果,若该文件中不存在该单词则提示错误信息。
    1614524-20190317224932616-1837476391.png

  • 功能选项3测试:

    用户输入想要查询统计的任意个数K个高频单词,查询成功则显示单词词频及其柱状图
    1614524-20190317224951083-1125430262.png

    若输入查询个数为不在有效范围内(负数或者大于文中单词类型个数),则提示相应的错误信息。
    1614524-20190317225004751-819627256.png

    1614524-20190317225014372-854771897.png

  • 功能选项4:

    退出程序,不在输出菜单。
    1614524-20190317225029634-1973755074.png

5. 代码片段

  • 读取指定文件
    String filecontent = "";//用来存放读取到的文件内容信息
        //用键值对分别存储单词和它出现的次数
        Map<String,Integer> map = new HashMap<String, Integer>();
        try {
            //读取指定文件DATA.txt,这里使用的是相对路径
//          FileInputStream fis = new FileInputStream("J:\\计算机科学与技术\\02 第二学期\\2  软件工程(代祖华)\\实验二 词频统计\\DATA.txt");
            FileInputStream fis = new FileInputStream("src\\DATA.txt");

            //创建BufferedReader的缓冲流,一次性读取很多数据,然后按要求分次交给上层调用者
            BufferedReader br = new BufferedReader(new InputStreamReader(fis));
            String str = "";
            try {
                //一行一行读取
                while ((str = br.readLine()) != null){
                    filecontent = filecontent + str;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
  • 分割字符串并统计键值对
        //arrspilt数组用来统计单词出现的次数
        String [] arrspilt = filecontent.split("[^a-zA-Z]+");
        for (int i=0;i<arrspilt.length;i++){

            //通过键名来获取键值
            if (map.get(arrspilt[i]) == null){
                //统计键值对
                map.put(arrspilt[i],1);
            }else {
                int count = map.get(arrspilt[i]);
                map.put(arrspilt[i],++count);
            }
        }
  • 对词频统计结果进行排序
        //利用TreeMap实现Comparator接口
        Comparator<Map.Entry<String, Integer>> valcom = new Comparator<Map.Entry<String,Integer>>() {

            //对词频统计结果进行排序
            public int compare(Map.Entry<String, Integer> rst1,Map.Entry<String, Integer> rst2) {
                
                        //降序排序
                int sortrst=rst2.getValue()-rst1.getValue();
            return sortrst;
                
                } 
            
            };
                
    List<Map.Entry<String, Integer>> ordlist = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
                
    // 用sort函数来排序
        Collections.sort(ordlist,valcom);
  • 将词频统计结果输出到指定文件results.txt中
                                //将词频统计结果输出到指定文件results.txt中
                try {
                    
                    FileWriter fw= new FileWriter("src\\results.txt");
                    BufferedWriter bw= new BufferedWriter(fw); 
                    for (Map.Entry<String, Integer> entry : ordlist) {
                        
                        bw.write(entry.getKey() + ":" + entry.getValue());  
                        bw.newLine();
                    }
                    bw.flush();//刷新
                    bw.close();//关闭
                    System.out.println("词频统计结果已输出到result.txt文件!");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
  • 统计任意单词在文件中出现次数
                                List<Map.Entry<String, Integer>> ordlist = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
                    
                // 用sort函数来排序
                Collections.sort(ordlist,valcom);
                
                Scanner sc = new Scanner(System.in); 
                        System.out.println("请输入想要统计出现在文章中的单词:"); 
                        String w = sc.next();
            
                for (Map.Entry<String, Integer> entry : ordlist) {
                
                    if(entry.getKey().equals(w)){//找到文件中与键盘录入单词相同的单词
                        word=entry.getKey();
                        count2=entry.getValue();
                        flag=1;
                        break;
                    }else{
                        flag=0;
                    }
                    
                }
                if(flag==1){
                    System.out.println("该单词"+word+"出现的个数为:"+count2);    
                }else{
                    System.out.println("对不起文章中没有出现该单词!");
                }
  • 显示K个高频词及其柱状图
            System.out.println("注:该文件中共有"+ordlist.size()+"个不同的单词!");
            Scanner sc = new Scanner(System.in); 
                System.out.println("请输入要查看的高频词频的个数:"); 
                int k = sc.nextInt();
                //String k=sc.next();
                
                //System.out.println(list.size());
                if(k>0&&k<=ordlist.size())//判断输入值是否超出范围
                {
                    System.out.println("----------词频最高的前"+k+"个单词及其柱状图-----------");
                    
                    for (Map.Entry<String, Integer> entry : ordlist) {

                        //System.out.println("单词 "+entry.getKey() + " 出现 " + entry.getValue()+" 次 ");
                        System.out.printf("单词 "+"%-8s" + "出现 " +"%-3d"+" 次 |",entry.getKey(),entry.getValue()); 

                                //用符号个数来模拟柱状图
                            for(int i=entry.getValue();i>0;i--)
                            {
                                System.out.print("⬛");
                            }
                            System.out.println();
                            //System.out.println(entry.getKey() + ":" + entry.getValue());
                            
                            if(--k==0)
                                break;//如果k==0则不再输出后面的词频                    
                        
                    }
                    System.out.println("------------------------------------------------"); 

                }else{
                    System.out.println("输入有误!请重新输入!");
                }
                
                

6. 总结:设计的程序如何实现软件设计模块化的原则

模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。

      在本程序中,需要实现全文单词个数及其词频统计,用户输入任意单词词频统计和任意个数高频词频统计及柱状图显示等多个功能,虽然这个程序只是一个小程序,但却也包含多个功能,如果我们将这若干个功能放在一个文件中,就会显得很臃肿,凌乱和复杂,在调试和维护时也很麻烦,最好的方式就是一个功能一个文件,将功能分散开来,用主程序,子程序等框架把软件的主要结构和流程描述出来,并定义和调试各部分模块,再通过主函数来实现对其他功能的调用,以功能块为单位进行程序设计,这样降低录了程序复杂度,使程序设计,调试等操作简单化。

7. PSP个人软件过程

PSP2.1任务内容计划共完成需要的时间(min)实际完成需要的时间(min)
Planning计划1010
•Estimate• 估计这个任务需要多少时间,并规划大致工作步骤1010
Development开发255295
••Analysis需求分析 (包括学习新技术)1015
•Design Spec• 生成设计文档57
•Design Review• 设计复审 (和同事审核设计文档)57
•Coding Standard代码规范 (为目前的开发制定合适的规范)56
•Design具体设计1010
•Coding具体编码200220
•Code Review• 代码复审510
•Test• 测试(自我测试,修改代码,提交修改)1520
Reporting报告1315
••Test Report• 测试报告43
•Size Measurement计算工作量44
•Postmortem & Process Improvement Plan• 事后总结 ,并提出过程改进计划58

      从本次这个词频统计程序的开发过程来看,我在做这项工作时是用来不少的时间,尤其是在开发过程中的编码设计阶段,由于很长时间没有再写代码,关于java好多知识都忘得差不多了,所以在编码时需要耗费时间来查资料,来纠错改错,但也基本完成了本次任务,看来日后要多加强代码的编写练习。

转载于:https://www.cnblogs.com/HaiYou667-GJ/p/10549413.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值