Github项目地址:https://github.com/jat0824/wc.git

项目相关要求



  wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。具体功能要求:程序处理用户需求的模式为:

wc.exe [parameter] [file_name]

PSP

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划  60 30 
· Estimate · 估计这个任务需要多少时间  700 630 
Development 开发  640 590 
· Analysis · 需求分析 (包括学习新技术)  90 90 
· Design Spec · 生成设计文档  30 30 
· Design Review · 设计复审 (和同事审核设计文档)  30 30 
· Coding Standard · 代码规范 (为目前的开发制定合适的规范)  20 15 
· Design · 具体设计  30 25 
· Coding · 具体编码  200 180 
· Code Review · 代码复审  60 40 
· Test · 测试(自我测试,修改代码,提交修改)  180 180 
Reporting 报告  120 100 
· Test Report · 测试报告  60 60 
· Size Measurement · 计算工作量  30 20 
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划  30 20 
  合计  820 720

遇到的困难及解决方法

  • 问题描述做过的尝试

    • 1、关于如何将参数传入main方法的问题
    • 2、如何统计词数
    • 3、如何判别注释段是否结束
    • 4、通配符的处理
  • 做过的尝试
    • 1、用Scanner类获取参数输入->使用main函数的argv数组获取参数输入

    • 2、逐行读取文件,除去特殊字符后用空格分离该行,返回数组长度

    • 3、设置了两个变量来记录注释段的开始字符个数和结束字符个数,只有两个变量相等的时候才表示注释段结束

    • 4、将通配符按正则表达式的规则替换掉了*和?

  • 成功解决问题

  • 收获:了解了main函数参数的作用,学习并运用了正则表达式,多角度思考问题

设计实现过程

包含以下几个函数:

  1、stringcount():实现-c、-l操作:统计文件字符数或行数

  2、wordcount():实现-w操作:统计指定文件中词的个数

  3、handleall():实现-s操作:递归读取目录下符合条件的文件,加入List

  4、moredata  ()  :实现-a操作: 统计代码行/空行/注释行

  5、Checkfile  ()  :判断需要处理的是目录还是文件

  6、deal  ()  :按正则表达式处理含通配符的文件名

  7、main():主方法

实现过程:

  在主方法中判断输入的参数并进行相应的操作,-s操作需要先调用Checkfile  () 函数,在Checkfile  () 函数中调用了deal  () 函数规范文件名,然后再调用了handleall()函数处理符合条件的文件。

关键代码

-s、-a操作实现:

在主函数中:首先判断参数是否为-s,然后调用Checkfile()方法判断输入的最后一个参数是目录还是文件,最后通过handleall()方法对符合条件的文件进行后续操作。

// 判断需要处理的是目录还是文件
public static void Checkfile()
{
int pathlen = filename.get(0).length();
int filelen = 0;
String name = null;
String file = filename.get(0);
// 判断是否为文件名,是否含有通配符
if (file.replaceAll("[^//.^//*^//?]", "").length()==0)  
{
handleall(file, "");
}else
{
if (file.contains("/"))
{
String[] n = file.split("/");
name = n[n.length-1];
filelen = name.length();
handleall(file.substring(0, pathlen-filelen), deal(name));
}
else
{
handleall("", deal(file));
}
}
} // 实现-s操作:递归读取目录下符合条件的文件,加入List
public static List<String> handleall(String path, String name) {
Matcher m = null;
if (path.equals(""))
{
dir = new File("src");
}else {
dir = new File(path);
}
File[] files = dir.listFiles();
if (files == null)
{
System.out.println("该目录为空!");
}
for (File f : files)
{
if (f.isFile()) {
if (name.equals(""))
{
filename.add(f.getAbsolutePath());
}else {
Pattern p = Pattern.compile(name);
m = p.matcher(f.getName());
if (m.matches())
{
filename.add(f.getAbsolutePath());
}
}
}else if (f.isDirectory()) {
handleall(f.getAbsolutePath(), name);
}
}
return filename;
} // 按正则表达式处理含通配符的文件名
public static String deal(String name)
{
name = name.replace(".", "#");
name = name.replaceAll("#", "\\.");
name = name.replace("*", "#");
name = name.replaceAll("#", ".*");
name = name.replace("?", "#");
name = name.replaceAll("#", ".?");
name = "^" + name + "$";
// System.out.println(name);
return name;
} // 实现-a操作
public static String moredata(int first) throws IOException {
int line = 0;
int null_line = 0; // 空行
// 用于匹配注释段的起始(/*)与结束(*/),只有当cp1==cp2时注释段才结束
int cp1 = 0;
int cp2 = 0;
// 标记整段注释的起始行数
int note = 0;
int end = 0;
int note_line = 0; // 注释行
int code_line = 0; // 代码行
File files = new File(filename.get(first));
if (files.exists()) { // 判断文件是否存在
BufferedReader br = new BufferedReader(new FileReader(files));
String st = null;
while ((st = br.readLine())!=null)
{ // 如果文件中最后一行为空行则最后一行不算一行
++line;
// 将字符串中的空格、回车、换行符、制表符去掉
String s = st.replaceAll("\\s*|\t|\r|\n", "");
if (s.equals("") || s.equals("{") || s.equals("}"))
{ // 判断空行用s.equals("")
// 注释段中的空行不算在空行数中,算在注释行数中
if (s.equals("") && cp1!=cp2)
{
;
}else {
null_line++;
}
}
else if (s.startsWith("//") || s.startsWith("{//") || s.startsWith("}//"))
{
note_line++;
}
else if (s.startsWith("/*"))
{
cp1++;
if (line>note && note!=0)
{
continue;
}else {
note = line;
}
}
else if (s.endsWith("*/")) {
cp2++;
if (line>end)
{
end = line;
}else {
continue;
}
if (cp2 == cp1)
{
note_line += end-note+1;
}
}
// 代码行=总行数-注释行-空行
code_line = line-note_line-null_line;
}
br.close();
System.out.println("文件" + filename.get(first) + "的代码行/空行/注释行 分别为: " + code_line + "/" + null_line + "/" + note_line);
return code_line + "/" + null_line + "/" + note_line;
} else {
System.out.println(files.getPath() + " 文件不存在!");
return "no such file!";
}
}
  • Checkfile()方法用于判断输入的路径是目录还是文件,再通过handleall()方法将各符合条件的文件绝对路径存入List表中。输入的是目录则递归对该目录下的所有文件进行后续操作,输入的是文件则直接对符合条件的文件进行后续操作(默认的文件路径在src目录下)

  • deal()方法是按正则表达式的规则处理含通配符的文件名,例如:输入的文件名为 *.?d 则经过处理后文件名为 ^.*..?d$

    • 其中^和$分别表示正则表达式的起始和终止
    • . 匹配除"\r\n"之外的任何单个字符; * 表示零次或多次匹配前面的字符或子表达式; ?表示零次或一次匹配前面的字符或子表达式;
  • moredata()方法中实现了对代码行、空行、注释行的统计,其中注释行的统计主要设置了两个int类变量cp1和cp2 对读取的每一行字符串进行判断,是否为"/*"开头,是则cp1++,是否为"*/"结尾,是则cp2++。因此只有当cp1==cp2的时候注释段才结束,这样设计主要针对注释段中含有注释段的特殊情况。并且注释段中的空行算在注释行数不算在空行数。

  • 运行结果截图:

    • 输入命令:

    • 结果输出:

测试运行

运行测试单元文件,运行结果截图:

项目小结

在一开始分析需求的时候没有彻底分析清楚需求,导致设计的时候没有考虑全面,在快结束的时候才发现需求没有完全实现。而且有些功能会有些不能解决的情况,例如:-w功能统计词数的时候如果两个词都顶格,分布在相邻两行或者中间隔着若干空行,则该功能会将两个词算为一个词。下次开发的时候不能粗略的按照自己的理解看完需求就马上开始设计,应该认真的看完需求文档之后再进行设计。在代码规范方面,应该在平时写代码的时候就养成好习惯,在需要解释说明的地方写好注释,代码的格式也应该有自己的风格。在开发完后可以给自己的项目写个用户说明文档以便用户使用。

           

个人项目:wc程序(java)的更多相关文章

  1. 个人项目-WC(Java实现)

    一.Github项目地址: https://github.com/kestrelcjx/-WC-Java- 二.PSP表格 PSP2.1 Personal Software Process Stage ...

  2. 个人项目-WC.exe (Java实现)

    一.Github项目地址:https://github.com/blanche789/wordCount/tree/master/src/main/java/com/blanche 二.PSP表格 P ...

  3. 个人项目wc(Java)

                                                      个人项目(Java) 一丶Github地址:https://github.com/SAH2019/S ...

  4. Implementation of WC in JAVA

    Implementation of WC in JAVA github地址 相关要求 基本功能 -c [文件名] 返回文件的字符数 (实现) -w [文件名] 返回文件的词的数目 (实现) -l [文 ...

  5. 个人项目-wc

    个人项目-WC   (C语言) 一.Github地址:https://github.com/Lin-J-F/WC 二.PSP表格 PSP2.1 Personal Software Process St ...

  6. 个人项目—WC

     一,Github地址:https://github.com/mushan520/WC.git 二.PSP表格: PSP2.1 Personal Software Process Stages 预估耗 ...

  7. 「小程序JAVA实战」springboot的后台搭建(31)

    转自:https://idig8.com/2018/08/29/xiaochengxujavashizhanspringbootdehoutaidajian31/ 根据下面的图,我们来建立下对应的sp ...

  8. Taurus.MVC 微服务框架 入门开发教程:项目集成:3、客户端:其它编程语言项目集成:Java集成应用中心。

    系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...

  9. 图解使用VS的安装项目打包程序

    背景 这段时间一直在做客户端程序的打包程序,遇到各种坑.因为以前没有任何这方面的经验,历经各种折腾,费尽九牛二虎之力总算是完成了. 虽然没有太多技术含量,但是因为挺繁琐的,所以还是在此记录一下. 由于 ...

随机推荐

  1. 解决spring 事务管理默认不支持SQLException等运行时异常

    公司同事在定位一个bug时,发现spring默认的事务只支持运行时异常的回滚,对于像SQLException这样的非运行时异常,默认的事务机制不能处理,于是找了下解决的办法:    1.在捕获SQLE ...

  2. RHEL6 64位ASM方式安装oracle 11gR2(一)

    本文转载自 http://vnimos.blog.51cto.com/2014866/1221361 一.安装前的准备 1.1 确定操作系统环境 1 2 3 4 5 6 7 8 9 10 11 12 ...

  3. mysql replication /mysql 主从复制原理

    一下内容均是根据leader的培训分享整理而成 ************************************我是分割线*********************************** ...

  4. file does not exist 阿里云OSS图片上传遇到的问题

    ./uploads\20171209/0497b8dd16e72c6fcf5bfd552f535a81.png file does not exist 原代码 function aliyun($sav ...

  5. python学习笔记(三):文件操作和集合

    对文件的操作分三步: 1.打开文件获取文件的句柄,句柄就理解为这个文件 2.通过文件句柄操作文件 3.关闭文件. 文件基本操作: f = open('file.txt','r') #以只读方式打开一个 ...

  6. SSD知识

    不管什么接口的SSD,一般都由以下部分组成:主控,Flash,板,壳,品牌.下面本佬就这些部分一一发帖,仅供娱乐参考,不作任何推荐和偏向,有不同见解请直接发表,有任何错误,请直接指正,不为吵架,只为娱 ...

  7. MVC原理图解

    注解: 视图中通过Action方法向控制器请求数据 控制器通过view()方法向视图呈现数据

  8. Python 中的 is 和 == 编码和解码

    一   is   与   ==   区别 ==    比较            比较的是值 例如: a = 'alex' b = 'alex' print(a == b) #True a = 10 ...

  9. openAS2搭建

    概要 秘钥生成工具 :链接:https://pan.baidu.com/s/1C3fnlkpu36mmpu8Y1fDnUA 密码:pg4k openas2  :链接:https://pan.baidu ...

  10. Gym101350 FMonkeying Around

    题意 有n只猴子排成一排,一共有m个笑话.开始时,这些猴子都坐在椅子上.下面m行给出的每个笑话包含三个整数x,l,k.代表猴子x讲了笑话l,所以距离x小于等于k的猴子如果他们从没听过这个笑话,他们会掉 ...