项目的github地址为(https://github.com/Fatead/WordCount)
PSP表格如下
PSP2.1 | PSP阶段 | 预估耗时实际耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 22 |
Estimate | 估计这个任务需要多少时 | 3 | 5 |
Development | 开发 | 580 | 650 |
- Analysis | - 需求分析(包括学习新技术) | 140 | 170 |
- Design Spec | - 生成设计文档 | 80 | 70 |
- Coding Standard | - 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
- Design | - 具体设计 | 20 | 20 |
- Coding | - 具体编码 | 180 | 210 |
- Code Review | - 代码复审 | 50 | 60 |
- Test | - 测试(自我测试,修改代码,提交修改) | 100 | 110 |
Reporting | 报告 | 100 | 145 |
- Test Report | - 测试报告 | 50 | 70 |
- Size Measurement | - 计算工作量 | 10 | 15 |
- Postmortem & Process Improvement Plan | - 事后总结, 并提出过程改进计划 | 40 | 60 |
合计 | 680 | 760 |
解题思路
看到题目中的的需求:对程序设计语言源文件统计字符数、单词数、行数,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。我立马就想到了上学期曾做的编译原理的课设自己动手做一个编译器,这个题目的解题思路大概是先利用文件读写操作对于源代码文件进行读取操作,然后将要分析代码的所有字符存放在一个字符数组中,接着对字符数组进行分析,对其进行一次或者多次扫描,然后储存或者输出分析结果。比如说如果对于单词进行统计,因为需求中给的定义为由空格或者逗号分隔开的都是单词,所以说要就要对于空格和逗号进行分析判断,还要考虑比如多个逗号或者空格连在一起的情况,并且回车也可以分隔单词。然后扩展功能的话如果要用停用词表,那么就需要将停用词表里面的所有单词存放在一个字符串数组中,源代码中所有的单词放在另一个,两个字符串数组的中的元素进行比对。找资料的话第一步就是关于Java的基本功能与基本语句,我参考的资料是Java高级程序设计和网上的一些技术博客,然后技术博客的网址在文章的最后,比如Java SE文档[1],Java字符串的处理[2],Java的文件操作[3]。
程序的设计实现过程
本程序只用了一个主类,然后一共有7个函数,分别是boolean类型的函数 isSpace(),isComma(),isEnter(),判断当前处理的字符是否为空格/逗号/回车等等,Read()函数即对于所选文件进行读取操作,并且将文件中的所有字符存在数组中。GetChar()函数,对于当前处理的字符进行分析,并对于注释行,空行与代码行进行分析。Process()对于源代码的字符数组进行处理,包括对于空格逗号回车的处理逻辑。最后就是程序的主函数main(String[] args)从命令行中中读入指令并进行相应的处理。并对前面所提到的六个函数进行调用。其中main函数的流程图如下:
代码说明
首先,程序的主函数会从命令行读入命令并进行分析。
public static void main(String[] args) //程序从控制台接收数据,数据会以字符串数组的形式保存在args里面
{
try
{
String filename = ""; //文件名
String outfile = "result.txt"; //输出信息文件名
String stoplist = "";
int i = 0;
int num = 0;
int length = args.length; //获取指令的个数
while(i<length)
{
if(args[i].equals("-a")) //如果需要
{
a = true;
i++;
}
else if(args[i].equals("-o"))
{
o = true;
i++;
outfile =args[i];
if((i+1) == args.length)
{
break;
}
i++;
}
else if(args[i].equals("-w"))
{
w = true;
i++;
}
else if(args[i].equals("-c"))
{
c = true;
i++;
}
else if(args[i].equals("-l"))
{
l = true;
i++;
}
else if(args[i].equals("-s"))
{
s = true;
i++;
}
else if(args[i].equals("-e"))
{
e = true;
i++;
stoplist=args[i];
if((i+1) == args.length)
{
break;
}
i++;
}
else if(args[i].charAt(0)!='-')
{
filename = args[i];
i++;
}
}
这一段代码就是从控制台接收命令进行分析,根据命令的具体的形式设置标志符。
if(e) //启用停用词表
{
Reader(stoplist,stop);
int j = 0;
while(j<stop.length)
{
SChar = stop[j];
while(SChar==' '||SChar==','||SChar=='\r')
{
j++;
SChar = stop[j];
change = true;
}
if(change)
{
num++; //停用词数加一
change = false;
}
stopArray[num] = stopArray[num]+stop[j];
j++;
}
}
如果从命令中查出需要启用停用符表,那么需要读取停用符表并把所有的停用符表的单词存起来。
if(Char == '/')
{
if(text[r+1]=='/') //判断是否有两个连载一起的"//"
{
exSign = true;
}
else if(text[r+1]=='*') //如果遇到/*则进入注释状态
{
exBegin = true;
r++;
}
}
else if(Char == '*')
{
if(text[r+1]=='/'&&exBegin)
{
exBegin = false;
exEnd = true;
r++;
}
}
else if(Char=='\n'||Char =='\0')
{
if(exBegin&&(code==0||code == 1))
{
exLine++;
code = 0;
}
else if(exBegin)
{
codeLine++;
code = 0;
}
else if(exEnd)
{
codeLine++;
code = 0;
exEnd = false;
}
else if((code==1&&exSign)||(code==0&&exSign)) //如果该行只有一个或者没有字符并且在"/*"的作用范围内
{
exLine++;
code = 0;
exSign = false;
}
else if(code==0||code==1)
{
empLine++;
exSign = false;
code = 0;
}
else
{
codeLine++;
exSign = false;
code = 0;
}
lineCount++;
}
这段是对源程序中的字符进行处理,并进行代码行,注释行和空行的分析工作。
public static void getAllFile(ArrayListsourceNameArray, String rootPath, String keyword, boolean s) //获取所有文件("*.c")
{
File rootFile = new File(rootPath);
File[] files = rootFile.listFiles();
if (files != null)
{
for (File f : files)
{
if (f.isDirectory() && s) //判断是文件夹
getAllFile(sourceNameArray, f.getPath(), keyword, true);
else if (f.getName().indexOf(keyword) == f.getName().length() - keyword.length())
sourceNameArray.add(f.getPath());
}
}
}
-s的功能的实现,对当前路径下的所有文件进行递归查找,直到找到符合要求的文件。
测试设计过程
本程序的测试主要采用了白盒测试的用例设计方法
具体测试过程如下:
[1][Java SE 文档] (http://www.oracle.com/technetwork/cn/java/javase/documentation/api-jsp-136079-zhs.html)
[2][Java如何将字符串放进字符串数组中](https://bbs.csdn.net/topics/390489032?list=lz)
[3][Java文件操作大全](http://www.cnblogs.com/fnlingnzb-learner/p/6010165.html)