Github:

https://github.com/whoNamedCody/WordCount

PSP表格 

PSP2.1

PSP阶段

预估耗时

(分钟)

实际耗时

(分钟)

Planning

计划

            10            15

· Estimate

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

            20            20

Development

开发

           180            250

· Analysis

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

            10            30

· Design Spec

· 生成设计文档

            10            20

· Design Review

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

            20               20

· Coding Standard

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

            10             20

· Design

· 具体设计

            20             20

· Coding

· 具体编码

           100            150

· Code Review

· 代码复审

            20            30

· Test

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

            50           100

Reporting

报告

            20            40  

· Test Report

· 测试报告

            30            40

· Size Measurement

· 计算工作量

            10            10

· Postmortem & Process Improvement Plan

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

             5            15
 

合计

           515           780

需求说明:

WordCount的需求可以概括为:对程序设计语言源文件统计字符数、单词数、行数,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。

1、基础功能:

-c:输出字符,

-l:输出代码行,

-w:输出单词,

-o:输出

2、 扩展功能:

-a:输出代码行/空行/注释行,

-s:递归处理文件,

-e:停用词表,

解题思路:

1、java实现,但需要转成exe在cmd下输入命令执行,所以流程是:编码(.java)-->Export(.jar)-->exe4j(.exe)

2、java里有static void main(String[] args),里面的args就是cmd下的命令数组,比如输入-c -l -w file.c(空格隔开),那么args数组长度为4

3、对args数组进行遍历分析,找出输入命令和文件名,比如-c -l -w -a 后面跟的是输入文件名,-s后面会跟*.c之类的通配文件,-e后面会跟停用词表stoplist.txt,-o接输出文件result.txt

这里识别出命令和文件后,会再对文件分析,比如-s  ./WordCount/*.c,需要截取出文件的上一层(相对)路径./WordCount和后缀.c,方便后续递归文件夹下的.c文件

4、将所有的统计封装成一个函数:public void command(String[] args,String inputFile,String outputFile,WordCount WC)

5、创建一个WordCount类,里面的属性有字符数,单词数,行数,代码行,空行,注释行,如果没有出现-s:则只实例化一个对象WordCount,调用一次command函数,输出前面的结果,如果出                           现 -s:即递归处理文件夹下面的*.c文件(当然*.txt,*.doc文件也是可以的),就声明多个WordCount对象,循环对对象属性进行赋值。如果需要输出就调用get和set方法获取属性值。

6、递归处理文件:根据相对路径递归寻找文件夹下的后缀文件。

程序设计实现:

类:

public class WordCount{}

函数方法设计:

WordCount(int,int,int,int,int,int)是构造函数;get和set是MyEclipse自动生成的的getter和setter方法,main(string [ ])是程序入口,分析判断指令格式;command(String [ ],String,String,WordCount)执行指令,返回相应指令的统计值;wc(String,String)对输入文件进行统计;inStop(String,String[ ])判断单词是否在停用词表内;getFile(File)递归获取文件。

代码说明:

1、执行命令:需要输出的有-c,-w,-l,-a,判断指令,直接暴力循环,优化日后再说。

 //命令执行,根据命令输出数据到屏幕和outputFile中
public void command(String[] args,String inputFile,String outputFile,WordCount WC)throws IOException{
String outResult="";
inputFile=inputFile.substring(inputFile.lastIndexOf("\\")+1, inputFile.length());
for(int i=0;i<args.length;i++){
if(args[i].equals("-c"))
outResult=outResult+inputFile+",字符数:" + WC.getCharCount()+"\r\n";
}
for(int i=0;i<args.length;i++){
if(args[i].equals("-w"))
outResult=outResult+inputFile+",单词数:" + WC.getWordCount()+"\r\n";
}
for(int i=0;i<args.length;i++){
if(args[i].equals("-l"))
outResult=outResult+inputFile+",行数:" + WC.getLineCount()+"\r\n";
}
for(int i=0;i<args.length;i++){
if(args[i].equals("-a"))
outResult=outResult+inputFile+",代码行/空行/注释行:"+WC.getCodeCount()+","
+WC.getSpaceCount()+","+WC.getNoteCount()+"\r\n";
}
//写数据到outputFile
System.out.println(outResult);
File writename = new File(outputFile);
writename.createNewFile();
BufferedWriter out = new BufferedWriter(new FileWriter(writename,true));
out.write(outResult);
out.flush();
out.close();
}

2、统计功能字符数、单词数、行数、代码行/空行/注释行

提一下代码行/空行/注释行

      匹配空行的正则表达式或则判断该行只有一个字符,则当前行为空行,匹配/*,如果存在,注释行++,标志进入注释行,继续匹配*/,如果不存在,注释行++,记下总共多少行,遇到*/,注释行++,标志结束注       
      释行,再匹配单行注释,其他的是代码行,最后计算注释的时候要减去只有/*没有 */的要加
 //统计功能字符数、单词数、行数、代码行/空行/注释行
public void wc(String inputFile,String stopFile) throws IOException{
String lineString = null;
String[] buffer=null; //文件每行
String[] buffer1 = null;//stoplist boolean isNote = false;
int notNote=0; //读取停用词表
if(useStop){
File dirr=new File(stopFile);
BufferedReader bff = new BufferedReader(new FileReader(dirr));
while((lineString=bff.readLine())!=null){
buffer1=lineString.split(",| ");
}
bff.close();
}
lineString = null; // 读取输入文件inputFile
File dir=new File(inputFile);
BufferedReader bf = new BufferedReader(new FileReader(dir));
while((lineString=bf.readLine())!=null){ //遇到 , 空格 就结束赋值
buffer=lineString.split(",| ");
for(int i=0;i<buffer.length;i++){ //使用停用词表则剔除词表内单词,不用则不踢
if(useStop){
if(!buffer[i].equals("")&&!inStop(buffer[i], buffer1)){
wordCount++;
}
}
else{
wordCount++;
} }
if(buffer.length!=1)
lineCount++; charCount+=(lineString.length()+1); lineString=lineString.trim();
//空行,一个字符的也算空行
if (lineString.matches("^[//s&&[^//n]]*$")||lineString.length()==1) {
spaceCount++;
}
//注释/*的开始
else if (lineString.startsWith("/*") && !lineString.endsWith("*/")||((lineString.startsWith("{/*")
||lineString.startsWith("}/*"))&&!lineString.endsWith("*/"))){
noteCount++;
isNote=true;
}
//没有遇到*/
else if(isNote&&!lineString.endsWith("*/")&&!lineString.startsWith("*/")) {
notNote++;
noteCount++;
}
//遇到*/
else if (isNote == true && (lineString.endsWith("*/")||lineString.startsWith("*/"))) {
noteCount++;
isNote=false;
}
//注释行
else if (lineString.startsWith("//")|| lineString.startsWith("}//")||lineString.startsWith("{//")||
((lineString.startsWith("{/*") ||lineString.startsWith("}/*")||lineString.startsWith("/*"))
&& lineString.endsWith("*/"))) {
noteCount++;
}
else{
codeCount++;
}
}
bf.close();
noteCount-=notNote;
codeCount+=notNote;
}
3、每次判断单词是否在停用词表内
 //判断是否在停用词表内
public static boolean inStop(String str,String[] buffer){
int count=0;
for(int i=0;i<buffer.length;i++){
if(str.equals(buffer[i])){
count++;
}
}
if(count>0)
return true;
else
return false;
}

4、遍历文件目录,如-s ./test/*.c则递归遍历./test目录下的.c文件

 //遍历目录文件
public static List<File> getFile(File dir) {
List<File> files = new ArrayList<File>();
// 此文件下的所有文件和文件夹集合
File[] subs = dir.listFiles();
for (File file : subs) {
if (file.isFile() && file.getName().endsWith(endStr)) {
// 把获取到的后缀文件添加到集合中,可以是任何后缀文件
files.add(file);
} else if (file.isDirectory())
//如果是目录,就进行递归
files.addAll(getFile(file));
}
return files;
}

测试设计过程:

    设计测试用例的思路是采用白盒测试的语句覆盖,尽可能把测试用例覆盖所有可能的程序语句,当然特别是分支语句,会多做测试,如-s的是否递归处理文件在我的程序中是一个分支语句

基本功能:

1、测试-c:输出file.c字符数

wc.exe -c file.c

2、测试-c、-w、-l:输出file.c字符数,单词数、行数 (当前根目录)

wc.exe -c -w -l file.c

3、测试-w 、-l 、-c:输出./testFile/file.c 字符数,单词数、行数 (根目录下其他路径,命令顺序)

wc.exe -w -l -c ./testFile/file.c

4、测试-c 、-l 、-w、-o:输出file.c字符数,单词数、行数、输出到文件resultAdd.txt

wc.exe -c -l -w file.c -o resultAdd.txt

扩展功能:

         5、测试-a:输出file.c的代码行/空行/注释行

wc.exe -a file.c

6、测试-s、-a:输出根目录下所有.c文件的代码行/空行/注释行

wc.exe -s -a *.c

7、测试-e:测试停用词表stoplist.txt

wc.exe -w file.c -e stoplist.txt

8、测试-c、-w、-l 、-a、-o:输出file.c字符数,单词数、行数 、代码行/空行/注释行输出到result.txt

wc.exe -c -w -l -a file.c -o result.txt

9、测试-a、-s、-e:测试递归,代码行/空行/注释行,停用词表stoplist.txt

wc.exe -a -s ./testFile/*.c -e stoplist.txt

10、测试-c、-w、-l、-a、-e、-o:对不递归进行测试

wc.exe -c -w -l -a file.c -e stoplist.txt -o result.txt

11、测试-c、-w、-l、-a、-s、-e、-o:覆盖所有的指令测试

测试脚本

         点击testScript.exe可以执行完11个测试用例,类似于批处理的方式,但只有一个进程,批处理测试用例。

下面是java代码,简单叙述一下思路:创建一个进程打开之前的wc.exe,逐行读取测试用例testCase.txt,一行是一条测试用例。

 package test;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner; public class TestScript {
//进程p
static Process p;
public static void main(String[] args) throws IOException{
String lineString=null;
File dirr=new File("testCase.txt"); //测试用例文件
if(dirr.exists()){
BufferedReader bff = new BufferedReader(new FileReader(dirr));
while((lineString=bff.readLine())!=null){
//非空行执行测试用例
if(!lineString.trim().matches("^[//s&&[^//n]]*$")){
System.out.println(lineString);
command(lineString);
}
}
bff.close();
}else{
System.out.println("没有该测试文件");
} Scanner sc = new Scanner(System.in);
String scc=sc.nextLine();
} public static void command(String cmd){
Runtime run = Runtime.getRuntime();//返回与当前 Java 应用程序相关的运行时对象
try {
p = run.exec(cmd);// 启动另一个进程来执行命令
BufferedInputStream in = new BufferedInputStream(p.getInputStream());
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
String lineStr;
while ((lineStr = inBr.readLine()) != null)
System.out.println(lineStr);
if (p.waitFor() != 0) {
if (p.exitValue() == 1)
System.err.println("命令执行失败!");
}
inBr.close();
in.close();
} catch (Exception e) {
e.printStackTrace();
}
} }

参考链接:

https://www.baidu.com

https://i.cnblogs.com/

https://bbs.csdn.net/

https://github.com/

WordCount--实现字符,单词,代码统计的更多相关文章

  1. 软件工程 wc.exe 代码统计作业

    软件工程 wc.exe 代码统计作业分享 1. Github 项目地址 https://github.com/EdwardLiu-Aurora/WordCount 更好地阅读本文,可点击这里 基本要求 ...

  2. WC 代码统计 java

    GitHub地址 项目需求 实现一个wc统计程序,可以对文本进行相关功能的统计与分析 基本功能 -c 统计字符数 -w 统计文件词数 -l 统计行数 扩展功能 -s 递归搜索目录下面的文件 -a 返回 ...

  3. Spark学习笔记1——第一个Spark程序:单词数统计

    Spark学习笔记1--第一个Spark程序:单词数统计 笔记摘抄自 [美] Holden Karau 等著的<Spark快速大数据分析> 添加依赖 通过 Maven 添加 Spark-c ...

  4. python 练习(一)代码统计工具的实现

    最近部门成立了一个python学习小组,旨在让大家在做项目中开始成长起来,于是老大就给布置了第一个小任务:代码统计工具,具体的需求如下: 需求: . 能够统计指定目录下C++程序的代码行数. . C+ ...

  5. Python实现代码统计工具——终极加速篇

    Python实现代码统计工具--终极加速篇 声明 本文对于先前系列文章中实现的C/Python代码统计工具(CPLineCounter),通过C扩展接口重写核心算法加以优化,并与网上常见的统计工具做对 ...

  6. Python代码统计工具

    目录 Python代码统计工具 声明 一. 问题提出 二. 代码实现 三. 效果验证 Python代码统计工具 标签: Python 代码统计 声明 本文将对<Python实现C代码统计工具(一 ...

  7. Python实现C代码统计工具(三)

    目录 Python实现C代码统计工具(三) 声明 一. 性能分析 1.1 分析单条语句 1.2 分析代码片段 1.3 分析整个模块 二. 制作exe Python实现C代码统计工具(三) 标签: Py ...

  8. Atitit. . 软件命名空间与类名命名单词的统计程序设计v2

    Atitit. . 软件命名空间与类名命名单词的统计程序设计v2 1. 要实现的目标1 1.1. Camel字符串模式的分词处理1 1.2. 多个大写的处理1 1.3. 数字与字幕的分离1 1.4.  ...

  9. 【学习笔记】C#中HashTable和快速排序的用法,从单词频率统计小程序写起

    先瞎扯点别的.进入这个神圣的地方总需要些鞭策,阿西巴,我是被鞭策进来摆摊的程序猿.软件工程老师说,写程序,发博客,就来博客园.这是个号召力很强的口号.最近看网络营销 搜索引擎优化的书多一些,只能说王老 ...

  10. Java实现 蓝桥杯VIP 算法提高 不同单词个数统计

    算法提高 不同单词个数统计 时间限制:1.0s 内存限制:512.0MB 问题描述 编写一个程序,输入一个句子,然后统计出这个句子当中不同的单词个数.例如:对于句子"one little t ...

随机推荐

  1. 机器学习_第三季_Series

    这一节没讲啥技术知识, 我就简单的罗列一下, 与numpy相似 1. 导入csv文件 import pandas as pdfandango = pd.read_csv("fandango_ ...

  2. sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set 的解决办法

    Linux新建用户 ,sudo报错: sudo: /usr/bin/sudo must be owned by uid 0 and have the setuid bit set 解决办法:重置一下s ...

  3. sql query skill

    https://www.w3resource.com/sqlite/sqlite-select-query-statement.php /* SELECT ChipID FROM "tb_X ...

  4. Lucas定理的运用及组合数奇偶性的判断

    组合数奇偶性的判断 对于C(n,k),若n&k == k 则c(n,k)为奇数,否则为偶数. 最直观的方法就是计算一下,然后看它的奇偶性:但是这个时间以及数据范围上都不允许: 另外一种方法就是 ...

  5. Spring Boot系列教程十:Spring boot集成MyBatis

    一.创建项目         项目名称为 "springboot_mybatis_demo",创建过程中勾选 "Web","MyBatis" ...

  6. 某 游戏公司 php 面试题

    1.实现未知宽高元素的水平垂直居中,至少两种方法. <div, class="father"> <div class="son">< ...

  7. Windows计划任务无法写Log的问题

    参照:https://www.cnblogs.com/jonezzz/p/10364153.html 使用WIndows计划任务去执行Exe文件时无法写Log,而Exe双击执行就能写Log,这是由于计 ...

  8. golang跨平台编译

    // 目标平台linux 64 SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build //目标平台windows SET CGO_ENA ...

  9. (十一)mybatis之整合ehcache缓存

    一.二级缓存 大家都知道使用mybatis就要先获取sqlsessionfactory,继而使用sqlsession来和数据库交互,每次只需要使用sqlsession对象提供的方法就好,当我们需要第一 ...

  10. (三)mybatis之通过接口加载映射配置文件

    1.1  需求 通过(二)在全局配置文件 mybatis-configuration.xml 通过 <mappers> 标签来加载映射文件,那么如果我们项目足够大,有很多映射文件呢,难道我 ...