Github地址: https://github.com/lllm-li/lllm
项目相关要求
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
基本功能列表:
wc.exe -c
file.c //返回文件
file.c 的字符数(实现)
wc.exe -w
file.c //返回文件
file.c 的词的数目 (实现)
wc.exe -l
file.c //返回文件
file.c 的行数(实现)
扩展功能:
wc.exe -s 递归处理目录下符合条件的文件。(实现)
wc.exe -a 返回更复杂的数据(代码行 / 空行 / 注释行)。(实现)
PSP
PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
Planning
计划
30
40
· Estimate
· 估计这个任务需要多少时间
40
60
Development
开发
900
1200
· Analysis
· 需求分析 (包括学习新技术)
180
150
· Design Spec
· 生成设计文档
40
60
· Design Review
· 设计复审 (和同事审核设计文档)
40
60
· Coding Standard
· 代码规范 (为目前的开发制定合适的规范)
20
60
· Design
· 具体设计
80
120
· Coding
· 具体编码
600
1000
· Code Review
· 代码复审
30
20
· Test
· 测试(自我测试,修改代码,提交修改)
120
60
Reporting
报告
120
240
· Test Report
· 测试报告
30
30
· Size Measurement
· 计算工作量
10
20
· Postmortem & Process Improvement Plan
· 事后总结, 并提出过程改进计划
60
30
合计
2300
3150
解题思路
看清项目的需求,设计流程框架,结合开发语言写出实现函数所用的方法,通过查阅资料开始编写代码,检测代码,修改代码。
设计的实现
代码分为三大部分:测试类wc,管理类wcManage,功能实现类wildCard、blankLine等
关系结构如下图所示
代码说明
wc主类的测试
public static void main(String args[]) throwsIOException {
wcManage wcmanage=newwcManage();
File f1=new File(args[1]);
String s=f1.getName();
wildCard fs=newwildCard();
File fk[]=fs.getFiles(f1.getParent(), s);for(File f:fk) {
wcmanage.setFileDirectory(f.getAbsolutePath());if(args[0].equals("-l")) {
System.out.println(f);
wcmanage.rowNumPrint();
}if(args[0].equals("-w")) {
System.out.println(f);
wcmanage.wordNumPrint();
}if(args[0].equals("-c")) {
System.out.println(f);
wcmanage.characterNumPrint();
}if(args[0].equals("-a")) {
System.out.println(f);
wcmanage.blankLinePrint();
wcmanage.codeLinePrint();
wcmanage.commentLinePrint();
}
}if(args[0].equals("-s"))wcmanage.recursivePrint();
}
wcManage类管理方法
String fileDirectory;voidrowNumPrint(){
rowNum rn=newrowNum();
rn.setFileDirectory(fileDirectory);
rn.rowNum();
System.out.println("行数:"+rn.rownum);
}voidwordNumPrint(){
wordNum wn=newwordNum();
wn.setFileDirectory(fileDirectory);
wn.wordNum();
System.out.println("词数:"+wn.wordnum);
}voidcharacterNumPrint(){
characterNum cn=newcharacterNum();
cn.setFileDirectory(fileDirectory);
cn.characterNum();
System.out.println("字符数:"+cn.characternum);
}voidblankLinePrint() {
blankLine bl=newblankLine();
bl.setFileDirectory(fileDirectory);
bl.blankLine();
System.out.println("空行数:"+bl.blankline);
}voidcodeLinePrint() {
codeLine cl=newcodeLine();
cl.setFileDirectory(fileDirectory);
cl.codeLine();
System.out.println("代码行:"+cl.codeline);
}voidcommentLinePrint() {
commentLine cl=newcommentLine();
cl.setFileDirectory(fileDirectory);
cl.commentLine();
System.out.println("注释行:"+cl.commentline);
}voidrecursivePrint() {
Recursive r=newRecursive();
r.setFileDirectory(fileDirectory);
System.out.println("所查询匹配的文件:");
r.Recursive();
}voidsetFileDirectory(String fileDirectory) {this.fileDirectory=fileDirectory;
}
空行数
public void blankLine(){//读取空行数
try{
String s;
String s1[];
Pattern p=Pattern.compile(REGEX);
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {if(s.matches("[\\s]*")) blankline++;else{
s1=p.split(s.trim());if(s1[0].length()==1&&s1.length==1)blankline++;
}
}
br.close();
}catch(Exception e) {
}
}
字符数
public void characterNum(){//读取字符数
try{
String s;
String s1[];
Pattern p=Pattern.compile(REGEX);
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {if(s.matches("[\\s]*")) continue;else{
s1=s.split(REGEX);for(int i=0;i
}
}
br.close();
}catch(Exception e) {
}
}
代码行
public void codeLine() {//读取代码行
try{
String s;
String s1[];
Pattern p=Pattern.compile(REGEX);
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {if(s.matches("[\\s]*")) continue;else{
s1=p.split(s.trim());if(s1.length>1||s1[0].length()>1)codeline++;
}
}
br.close();
commentLine cl=newcommentLine();
cl.setFileDirectory(fileDirectory);
cl.commentLine();
codeline-=cl.commentline;
}catch(Exception e) {
}
}
注释行
public void commentLine() {//读取注释行
try{
String s;int i=0,j=0;
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {
i++;if(s.indexOf("//")!=-1)commentline++;if(s.indexOf("/*")!=-1) j=i;if(s.indexOf("*/")!=-1) commentline+=i-j+1;
}
br.close();
}catch(Exception e) {
}
}
递归处理
public void Recursive() {//读取目录下的文件
File file=newFile(fileDirectory);
file=newFile(file.getParent());
fs=file.listFiles();for(File f:fs) {if(!f.isDirectory()) {
System.out.println(" "+f);
};
}
}
行数
public void rowNum(){//读取行数
try{
String s;
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {
rownum++;
}
br.close();
}catch(Exception e) {
}
}
通配符
public staticFile[] getFiles(String filepath,String filename) {
File file= newFile(filepath);
filename=filename.replace("*", ".*");
filename=filename.replace("?", ".?");
Pattern p=Pattern.compile(filename);
ArrayList list =filePattern(file, p);
File f[]= newFile[list.size()];returnlist.toArray(f);
}private static ArrayListfilePattern(File file, Pattern p) {if(file.isFile()) {
Matcher matcher=p.matcher(file.getName());if(matcher.matches()) {
ArrayList list = new ArrayList();
list.add(file);returnlist;
}
}else if(file.isDirectory()) {
File[] files=file.listFiles();if (files!=null && files.length>0) {
ArrayList list = new ArrayList();for (int i = 0; i < files.length; i++) {
ArrayList rlist =filePattern(files[i], p);if (rlist != null) {
list.addAll(rlist);
}
}returnlist;
}
}return null;
}
词数
public void wordNum(){//读取词的数目
try{
String s;
Pattern p=Pattern.compile(REGEX);
BufferedReader br=new BufferedReader(newFileReader(fileDirectory));while((s=br.readLine())!=null) {if(s.matches("[\\s]*"))continue;
wordnum+=p.split(s).length;
}
br.close();
}catch(Exception e) {
}
}
测试文件
测试结果:
遇到的困难:
通配符模式的实现,无法得到所写字符串变成正则表达式。
解决办法:
通过查询资料得到 Pattern p=Pattern.compile(REGEX);即可将所要字符串变成正则表达式
总结:
结构清晰,但是代码冗余量较大,实现基本功能和扩展功能。同时也学会了github上传的方法。测试代码要具有代表性,否则会导致漏掉细节而导致功能出错,同时也复习了正则表达式,了解了项目开发的基本流程,收获还是很大的。
改进原代码可以把基本功能和扩展功能一并写到一个类,这样可以减少代码的冗余量。