zoukankan      html  css  js  c++  java
  • 词频统计单元测试

      我这次用构造单词树的形式进行词频统计,此次的任务是对已有的程序进行单元测试。选用的工具是JUnit。它是基于测试驱动开发(TDD)原理的。 

      此次词频统计的主体思想是,每次读入文章中的128(自己设定)个字符(目的是防止溢出),将这些字符存储到一颗树中,树中的节点有一个存储词频的变量和一个指向子节点的数组(类似于c语言中的指针)。最后遍历整棵树,按照词频进行排序。

    下面是我的片段代码

    下面这段代码是定义的节点的结构

    class CharTreeNode{
        int count=0;
        CharTreeNode children[]=new CharTreeNode[26];
    }

    下面这段代码是全局变量的声明,因为涉及到建树时都是从根节点开始生成,所以根节点定义为全局变量

    //设置为全局变量,每读入一行,在原来生成的树的基础上继续生成子节点
        public static CharTreeNode root=new CharTreeNode();
        public static CharTreeNode p=root;
        private static FileReader reader=null;
        private static BufferedReader buffer=null;
        private Scanner scan;

    下面这段代码实现的是对每个输入的字符串进行树的构造,最后返回的是树的根。

    /*
         * 生成单词树
         * */ 
        public static CharTreeNode generateCharTree(String text) {
            char c = ' ';
            for (int i = 0; i < text.length(); i++) {
                c = text.charAt(i);
                if (c > 'A' && c < 'Z') {
                    c = (char) (c + 'a' - 'A'); // 变大写字母为小写字母
                }
                if (c >= 'a' && c <= 'z') {
                    if (p.children[c - 'a'] == null) {
                        p.children[c - 'a'] = new CharTreeNode();
                    }
                    p = p.children[c - 'a'];
                } else {
                    p.count++;
                    p = root;
                }
            }
            if (c >= 'a' && c <= 'z')
                p.count++;
            return root;
        }

    下面这段代码用方法重载的形式遍历整棵树,然后将遍历到的单词存储在List

        /*
         * 遍历整棵树,将遍历得到的每个单词存到list中
         * */ 
        public static void searchTree(List<Word> list, CharTreeNode node, char buffer[], int len) {
            for (int i = 0; i < 26; i++) {
                if (node.children[i] != null) {
                    buffer[len] = (char) (i + 'a');
                    if (node.children[i].count > 0) { // 遍历到了单词的最后一个字母
                        Word word = new Word();
                        word.setNum(node.children[i].count);
                        word.setWord(String.valueOf(buffer, 0, len + 1));
                        list.add(word);
                    }
                    searchTree(list, node.children[i], buffer, len + 1); // 递归调用,每次以上一个叶节点作为下次递归的头结点
                }
            }
        }
    
        /*
         * searchTree()为重载的方法
         * */ 
        public static void searchTree(List<Word> list, CharTreeNode node) {
            searchTree(list, node, new char[100], 0);
        }

    下面这段代码是对不同路径构造的树数进行单词的排序和输出

    /*
         * 对文章用generateCharTree()函数生成单词树,在对生成的单词树进行排序并且输出
         */
        public static void sortAndOutput(String filePath) throws IOException {
            reader = new FileReader(filePath);
            buffer = new BufferedReader(reader);
            char c[] = new char[128]; // 防止读入一行太长而出现溢出的情况
            int len;
            String temp = ""; // 存储buffer读出的字符
            String lastWord = ""; // 若读出的最后一个字符是字母,lastWord存储那个字符所在的单词,lastWord就被加到下一轮的temp中
            while ((len = buffer.read(c)) > 0) {
                temp = ""; // 清空上一轮temp的内容
                temp += lastWord;
                for (int i = 0; i < len; i++) {
                    temp += c[i];
                }
                lastWord = ""; // 清空上一轮lastword的内容
                if (Character.isLetter(c[len - 1])) { // 当128个字符的最后一个字符为字母时,就得分情况讨论
                    int j, t;
                    for (j = len - 1, t = 0; Character.isLetter(c[j]); j--, t++)
                        ; // t代表最后一个字符(c[len-1])为字符时,前面有几个连续的字符
                    temp = temp.substring(0, temp.length() - t); // 当检测到最后一个字符为字母时,直接将最后一个字符所在的单词剔除本轮的temp,而转接到下一轮的temp中
                    for (int k = j + 1; k < len; k++) {
                        lastWord += c[k];
                    }
                }
                root = generateCharTree(temp);
            }
            List<Word> list = new ArrayList<Word>();
            searchTree(list, root);
            // 对生成的单词树按照单词的次数逆向排序排序
            Collections.sort(list, new Comparator<Object>() {
                @Override
                public int compare(Object o1, Object o2) {
                    Word word1 = (Word) o1;
                    Word word2 = (Word) o2;
                    return word2.getNum() - word1.getNum();
                }
            });
            buffer.close();
            reader.close();
            root=new CharTreeNode();  //但对于输入的是目录时,对每篇文章建立的树统计完后,应当初始化这棵树,便于下篇文章建树
            System.out.println("单词	数量");
            for (int i = 0; i < 5; i++) {
                System.out.println(((Word) list.get(i)).getWord() + "	" + ((Word) list.get(i)).getNum());
            }
        }

    下面进入此次的重头戏:单元测试。引入Junit后在每个测试的方法前加上@Test,选中方法名即可测试

    下面这段代码是对输入目标的文件的路径进行该文件的词频统计

    @Test
        public void testInputFilePath() throws IOException {
            scan = new Scanner(System.in);
            String filePath = scan.next();
            while (filePath != null) {
                sortAndOutput(filePath);
                filePath = scan.next();
            }
        }

    结果截图如下

          

    下图当输入的文件名找不到时

    下面这段代码是对输入目标文件的文件名进行该文件的词频统计

    @Test
        public  void testInputFileName() throws IOException {
            scan = new Scanner(System.in);
            String filePath = scan.next();
            sortAndOutput("F:\document\" + filePath);
        }

    结果截图如下

    下面这段代码是对输入目标文件所在的目录名,进行该文件的词频统计

    @Test
        public void testInputDirectoryPath() throws IOException {
            scan = new Scanner(System.in);
            String DirectoryPath = scan.next();
            File f = new File(DirectoryPath);
            File s[] = f.listFiles();
            for (int i = 0; i < s.length; i++) {
                String fileName = s[i].getName();
                if (fileName.endsWith(".txt")) {
                    sortAndOutput(DirectoryPath + "\" + fileName);
                }
            }
        }

    结果截图如下

    下面这段代码测试重定向输入

    @Test
        public void reDirectInputByConsole() throws IOException {
            Scanner scan = new Scanner(System.in);
            String command = scan.nextLine();
            String filePath = command.substring(command.indexOf("<") + 1);
            reader = new FileReader(filePath.trim());
            buffer = new BufferedReader(reader);
            String line = null;
            line = buffer.readLine();
            String targetFile = "F:\document\new.txt";
            FileWriter out = new FileWriter(targetFile);
            while (line != null) {
                out.write(line + "
    ");
                line = buffer.readLine();
            }
            out.close();
            buffer.close();
            reader.close();
            sortAndOutput(targetFile);
        }
    }

    结果如下

    测试后的感受:

     测试过程中发现了程序的bug,比如在测试输入目录时,因为没将数进行清空,下一篇文章的单词会追加到以前的树上,通过单元测试解决了这个问题。

  • 相关阅读:
    网站安全编程 黑客入侵 脚本黑客 高级语法入侵 C/C++ C# PHP JSP 编程
    【算法导论】贪心算法,递归算法,动态规划算法总结
    cocoa2dx tiled map添加tile翻转功能
    8月30日上海ORACLE大会演讲PPT下载
    【算法导论】双调欧几里得旅行商问题
    Codeforces Round #501 (Div. 3) B. Obtaining the String (思维,字符串)
    Codeforces Round #498 (Div. 3) D. Two Strings Swaps (思维)
    Educational Codeforces Round 89 (Rated for Div. 2) B. Shuffle (数学,区间)
    洛谷 P1379 八数码难题 (BFS)
    Educational Codeforces Round 89 (Rated for Div. 2) A. Shovels and Swords (贪心)
  • 原文地址:https://www.cnblogs.com/liquan/p/5904068.html
Copyright © 2011-2022 走看看