个人项目作业-Word Count
个人项目作业
1.Github地址
https://github.com/CLSgGhost/SE_work
2.项目相关需求
wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:
wc.exe [parameter] [file_name]
基本功能列表:
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的词的数目
wc.exe -l file.c //返回文件 file.c 的行数
扩展功能:
    -s   递归处理目录下符合条件的文件。
    -a   返回更复杂的数据(代码行 / 空行 / 注释行)。
空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
代码行:本行包括多于一个字符的代码。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
} //注释
在这种情况下,这一行属于注释行。
[file_name]: 文件或目录名,可以处理一般通配符。
高级功能:
-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。
需求举例:
  wc.exe -s -a *.c
返回当前目录及子目录中所有*.c 文件的代码行数、空行数、注释行数。
3.PSP估计开发时间
| PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 
|---|---|---|
| Planning | 计划 | 20 | 
| · Estimate | · 估计这个任务需要多少时间 | 20 | 
| Development | 开发 | 635 | 
| · Analysis | · 需求分析 (包括学习新技术) | 240 | 
| · Design Spec | · 生成设计文档 | 20 | 
| · Design Review | · 设计复审 (和同事审核设计文档) | 10 | 
| · Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 5 | 
| · Design | · 具体设计 | 60 | 
| · Coding | · 具体编码 | 120 | 
| · Code Review | · 代码复审 | 60 | 
| · Test | · 测试(自我测试,修改代码,提交修改) | 120 | 
| Reporting | 报告 | 60 | 
| · Test Report | · 测试报告 | 20 | 
| · Size Measurement | · 计算工作量 | 20 | 
| · Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 20 | 
| 合计 | 715 | 
4.解题思路
- 使用的编程语言:以往都是用C写代码,这次项目尝试用C++写一下。
 - 需要学习到的知识:string流的使用、正则表达式等。
 - 寻找资料的方式:通过博客学习,实在难以理解时询问有经验的朋友。
 - 思考细节:因为要做的是一个word count程序,而word count是存在的一个工具,可以通过了解word count的详细功能来进一步理解需求,并模 仿word count完成自己的程序。
 - 遇到的困难:以前没有接触到处理文件的程序写法,各种处理文件的函数处理方式十分陌生,容易遇到难以发现的bug。
 
5.设计实现过程
- 输入输出:按照需求上的输入方式制定用户输入格式,给出指令菜单,然后按指令给出相关输出。
 - 功能实现方式:需要实现的功能很明确,代码量应该不会很大,采用一个功能一个函数的方式实现,通过主函数调用各个功能的函数。 将所有 函数定义在一个类里面,主函数直接调用。
 
- 功能函数定义:
int Char_count(string File_name); //统计字符数
int Word_count(string File_name); //统计单词数
int Line_count(string File_name); //统计行数
int NullLine_count(string File_name); //统计空行数
int ComLine_count(string File_name); //统计注释行数
int CodeLine_count(string File_name, int L1, int L2); //统计代码行数 - 实现细节: 注意到 行数 = 空行数 + 注释行数 + 代码行数,干脆只实现行数、空函数和注释行数的统计函数,剩下代码行数的统计可以直接用 行数 - 空行数 - 注释行数 得到,减少开发时间。
 
6.代码说明
//主函数
1 int main()
2 {
3 char c;
4 Word_Count wc;
5 ifstream file;
6 string Order, File_name;
7 cout << "输入格式:wc.exe(空格)[parameter](空格)[file_name]" << endl << endl;
8 cout << "功能列表:-c 统计文件字符数" << endl;
9 cout << " -w 统计文件单词数" << endl;
10 cout << " -l 统计文行数数" << endl;
11 cout << " -a 统计文件空行数、注释行数、代码行数" << endl << endl;
12 while (1)
13 {
14 cout << "wc.exe" << " ";
15 cin >> Order >> File_name;
16 file.open(File_name, ios::in);
17 if (!file.is_open()) //查找文件失败
18 {
19 cout << "文件不存在,无法打开" << endl << endl;
20 continue;
21 }
22 c = file.get();
23 if (c == EOF) //文件为空
24 {
25 cout << "文件为空" << endl;
26 }
27 if (Order[0] == '-')
28 {
29 switch (Order[1])
30 {
31 case 'c':wc.Ch_count = wc.Char_count(File_name); //统计字符数
32 cout << "文件字符数为:" << wc.Ch_count << endl << endl;
33 break;
34 case 'w':wc.Wo_count = wc.Word_count(File_name); //统计单词数
35 cout << "文件单词数为:" << wc.Wo_count << endl << endl;
36 break;
37 case 'l':wc.Li_count = wc.Line_count(File_name); //统计行数
38 cout << "文件总行数为:" << wc.Li_count << endl << endl;
39 break;
40 case 'a':
41 wc.NuLi_count = wc.NullLine_count(File_name); //统计空行数
42 wc.CmLi_count = wc.ComLine_count(File_name); //统计空行数
43 wc.CdLi_count = wc.CodeLine_count(File_name, wc.NuLi_count, wc.CmLi_count);//统计代码行数
44 cout << "文件空行数为:" << wc.NuLi_count << endl;
45 cout << "文件注释行数为:" << wc.CmLi_count << endl;
46 cout << "文件代码行数为:" << wc.CdLi_count << endl << endl;
47 break;
48 default:
49 cout << "无效指令" << endl << endl;
50 break;
51 }
52 }
53 file.close();
54 }
55 system("pause");
56 return 0;
57 }
//统计字符数
1 int Word_Count::Char_count(string File_name) //统计字符数
2 {
3 int n1 = 0;
4 char ch;
5 ifstream f;
6 f.open(File_name, ios::in);
7 f >> ch;
8 while (!f.eof())
9 {
10 f >> ch; //逐个读入字符并统计数量
11 n1++;
12 }
13 f.close();
14 return n1;
15 }
//统计单词数
1 int Word_Count::Word_count(string File_name) //统计单词数
2 {
3 int n2 = 0;
4 char ch;
5 ifstream f;
6 f.open(File_name, ios::in);
7 while (!f.eof())
8 {
9 ch = f.get();
10 if ((ch >= 'A'&& ch <= 'Z') || (ch >= 'a'&& ch <= 'z')) //发现单词
11 {
12 while ((ch >= 'A'&& ch <= 'Z') || (ch >= 'a'&& ch <= 'z'))
13 {
14 ch = f.get(); //读取字符直到退出单词
15 }
16 n2++; //单词计数器+1
17 }
18 }
19 f.close();
20 return n2;
21 }
//统计行数
1 int Word_Count::Line_count(string File_name) //统计行数
2 {
3 int n3 = 0;
4 char ch;
5 ifstream f;
6 f.open(File_name, ios::in);
7 ch = f.get();
8 if (ch == EOF) //文件为空则返回0
9 {
10 return 0;
11 }
12 while (!f.eof())
13 {
14 if (ch == '\n') //读取到换行符时行数+1
15 {
16 n3++;
17 }
18 ch = f.get();
19 }
20 f.close();
21 return n3 + 1;
22 }
//统计空行数
1 int Word_Count::NullLine_count(string File_name) //统计空行数
2 {
3 int n4 = 0, i = 0;
4 char ch;
5 char str[2000];
6 bool is_comline = 0; //判断当前行是否在注释行"/*...*/"内
7 string s;
8 string pattern = "^[\\s]{1,}[\\S]?"; //正则表达式,匹配任何空字符一个以上和非空字符0或1个
9 regex exception(pattern);
10 fstream f;
11 f.open(File_name, ios::in); //打开文件
12 ch = f.get();
13 if (ch == EOF) //文件为空则返回0
14 {
15 return 0;
16 }
17 while (!f.eof()) //判断文件是否读取完毕
18 {
19 getline(f, s); //逐行读取文件
20 i = 0; //i初始化
21 if (!s.empty())
22 {
23 strcpy_s(str, s.c_str()); //string非空就则转换位字符数组
24 }
25 while (str[i] == ' ' || str[i] == '\t') //过滤空格和'\t'
26 {
27 i++;
28 }
29 if (str[i] == '/' && str[i + 1] == '*') //读取到'/*',开始注释行识别
30 {
31 is_comline = 1;
32 i += 2;
33 }
34 while (is_comline == 1 && str[i] != '\0')
35 {
36 if (str[i] == '*' && str[i + 1] == '/') //读取到'*/',结束注释行识别
37 {
38 is_comline = 0;
39 }
40 i++;
41 }
42 s.erase(0, 1);
43 if (s.empty() && is_comline == 0) //判断读取的行是否只有回车换行符
44 {
45 n4++;
46 continue;
47 }
48 if (regex_match(s, exception) && is_comline == 0)
49 {
50 n4++; //匹配任何空字1个以上,非空字符只有0或1个的空行 ,且不在注释行内则空行数增加
51 }
52 }
53 f.close();
54 return n4;
55 }
//统计注释行数
1 int Word_Count::ComLine_count(string File_name) //统计注释行数
2 {
3 int n5 = 0, i = 0;
4 char str[2000];
5 bool is_comline = 0;
6 ifstream f;
7 f.open(File_name, ios::in); //打开文件
8 while (!f.eof()) //判断文件是否读取完毕
9 {
10 f.getline(str, 2000); //逐行读取文件
11 i = 0; //i初始化
12 if (str[0] == '}')
13 {
14 i++;
15 }
16 while (str[i] == ' ' || str[i] == '\t') //过滤空格和'\t'
17 {
18 i++;
19 }
20 if (str[i] == '/' && str[i + 1] == '/') //读取'//'
21 {
22 if (is_comline == 0) //当前行不在注释'/*...*/'内,注释行加一
23 {
24 n5++;
25 continue;
26 }
27 }
28 if (str[i] == '/' && str[i + 1] == '*') //读取到'/*',开始注释行计算
29 {
30 is_comline = 1;
31 i += 2;
32 }
33 if (is_comline == 1)
34 {
35 n5++; //当前行在注释'/*...*/'内,注释行加一
36 }
37 while (is_comline == 1 && str[i] != '\0')
38 {
39 if (str[i] == '*' && str[i + 1] == '/') //读取到'*/',结束注释行计算
40 {
41 is_comline = 0;
42 }
43 i++;
44 }
45 }
46 f.close();
47 return n5;
48 } //注:不考虑注释符'/*...*/'不闭合的情况。若出现'/*'而没有'*/',默认文本本身出错且'/*'以下全为注释行
//统计代码行数
1 int Word_Count::CodeLine_count(string File_name, int L1,int L2) //统计代码行数
2 {
3 int n6 = 0;
4 int L = 0; //定义总行数
5 Word_Count w;
6 L = w.Line_count(File_name);
7 n6 = L - L1 - L2; //注释行数 = 总行数 - 空行数 - 注释行数
8 return n6;
9 }
7.测试运行
- 已实现功能:
 
-c -w -l -a
- 具体测试截图:
 
//空文件测试

//单字符文件测试

//单个词文件测试

//单行文件测试

//典型文件测试

//错误输入提示

8.完整PSP
| 
 PSP2.1  | 
 Personal Software Process Stages  | 
 预估耗时(分钟)  | 
 实际耗时(分钟)  | 
| 
 Planning  | 
 计划  | 
 20  | 
 20  | 
| 
 · Estimate  | 
 · 估计这个任务需要多少时间  | 
 20  | 
 20  | 
| 
 Development  | 
 开发  | 
 635  | 
 725  | 
| 
 · Analysis  | 
 · 需求分析 (包括学习新技术)  | 
 240  | 
 240  | 
| 
 · Design Spec  | 
 · 生成设计文档  | 
 20  | 
 20  | 
| 
 · Design Review  | 
 · 设计复审 (和同事审核设计文档)  | 
 10  | 
 10  | 
| 
 · Coding Standard  | 
 · 代码规范 (为目前的开发制定合适的规范)  | 
 5  | 
 5  | 
| 
 · Design  | 
 · 具体设计  | 
 60  | 
 60  | 
| 
 · Coding  | 
 · 具体编码  | 
 120  | 
 150  | 
| 
 · Code Review  | 
 · 代码复审  | 
 60  | 
 90  | 
| 
 · Test  | 
 · 测试(自我测试,修改代码,提交修改)  | 
 120  | 
 150  | 
| 
 Reporting  | 
 报告  | 
 60  | 
 90  | 
| 
 · Test Report  | 
 · 测试报告  | 
 20  | 
 20  | 
| 
 · Size Measurement  | 
 · 计算工作量  | 
 20  | 
 20  | 
| 
 · Postmortem & Process Improvement Plan  | 
 · 事后总结, 并提出过程改进计划  | 
 20  | 
 50  | 
| 
 合计  | 
 715  | 
 835  | 
9.项目小结
看到要做个人项目作业的时候其实我还是比较懵逼的,感觉还什么都不会,然后就要来写个人项目,不过还是一点点看博客,一点点学,终于算是做了出来,由于个人能力问题与时间问题,很多功能都还没实现,希望在以后的学习中能学习到其他功能的实现方法。
从PSP来看,实际开发时间远超预估,即使是预估已有所保留空余时间的情况下。从而看出两个问题:1.对自己编程水平还不够了解。2.对我个人来说项目难度超出预期。而且就开发过程来看,程序中许多写法还有很大的优化空间。希望在以后的学习里能不断磨练自己,让自己成长为一个有能力的软件开发者。
个人项目作业-Word Count的更多相关文章
- 【2016.3.22】作业 Word count 小程序
		
今天更下word count程序的设计思路及实现方法. 我的程序贴在coding里,这里就先不贴出来了, 我的coding地址:https://coding.net/u/holy_angel/p/wo ...
 - 第三周作业————————word count
		
#include <stdio.h> void main() { FILE *fp; , str, word, pu, ch; int g; str = ; word = ; pu = ; ...
 - Word Count(C语言)
		
1.项目地址 https://github.com/namoyuwen/word-count 2.项目相关要求 2.1 项目描述 Word Count 1. 实现一个简单而完整的软件工具(源程序 ...
 - 个人项目作业——wc.exe
		
一.Github项目地址 https://github.com/PIPIYing/wc 二.项目概况 项目描述 Word Count 1. 实现一个简单而完整的软件工具(源程序特征统计程序). 2. ...
 - Word Count作业
		
Word Count作业 一.个人Gitee地址:https://gitee.com/Changyu-Guo 二.项目简介 该项目主要是模拟Linux上面的wc命令,基本要求如下: 命令格式: wc. ...
 - Java --本地提交MapReduce作业至集群☞实现 Word Count
		
还是那句话,看别人写的的总是觉得心累,代码一贴,一打包,扔到Hadoop上跑一遍就完事了????写个测试样例程序(MapReduce中的Hello World)还要这么麻烦!!!?,还本地打Jar包, ...
 - 软件工程第三个程序:“WC项目” —— 文件信息统计(Word Count ) 命令行程序
		
软件工程第三个程序:“WC项目” —— 文件信息统计(Word Count ) 命令行程序 格式:wc.exe [parameter][filename] 在[parameter]中,用户通过输入参数 ...
 - 个人项目作业WC(JAVA)
		
GitHub地址:https://github.com/1666403186/WC 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试.回归 ...
 - mac上eclipse上运行word count
		
1.打开eclipse之后,建立wordcount项目 package wordcount; import java.io.IOException; import java.util.StringTo ...
 
随机推荐
- TCP中RTT的测量和RTO的计算
			
https://blog.csdn.net/zhangskd/article/details/7196707 tcp传输往返时间是指:发送方发送tcp断开时, 到发送方接收到改段立即响应的所耗费的时间 ...
 - MySQL索引结构之Hash索引、full-text全文索引(面)
			
Hash索引 主要就是通过Hash算法(常见的Hash算法有直接定址法.平方取中法.折叠法.除数取余法.随机数法),将数据库字段数据转换成定长的Hash值,与这条数据的行指针一并存入Hash表的对应位 ...
 - C/C++中内存对齐问题的一些理解(转)
			
内存对齐指令 一般来说,内存对齐过程对coding者来说是透明的,是由编译器控制完成的 如对内存对齐有明确要求,可用#pragma pack(n)指定,以n和结构体中最长数据成员长度中较小者为有效值 ...
 - linux服务器间配置ssh免密连接
			
先说一下,我用的centos7,root用户.ssh的原理就不说了,网上介绍的文章很多,直接开始说操作步骤吧: 1.首先确认有没有安装ssh,输入 rpm -qa |grep ssh查看 这样就表示安 ...
 - 储存与RAID--独立磁盘阵列
			
存储: 专门用来插硬盘的机器,作用是增加插口,可以多插硬盘. 这种有策略保证硬盘坏了,数据不丢.而本地磁盘坏了,会导致数据丢失,故一般操作系统放在本地磁盘.而数据放在存储盘. 存储里依然有:cpu( ...
 - Go语言配置管理神器——Viper中文教程
			
Viper是适用于Go应用程序的完整配置解决方案.它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式. Viper Viper是适用于Go应用程序的完整配置解决方案.它被设计用于在应用 ...
 - 【C++】递归之二分查找
			
简单查找的时间复杂度为O(n) 二分查找的时间复杂度为O(logn) 用递归实现二分查找: 基线条件:数组只包含一个元素.如果如果要查找的值与这个元素相同,就找到了:否则说明不在数组中. 递归条件:把 ...
 - kali 系列学习07-攻击之密码生成
			
比较理想的字典是拖库字典,比如CSDN字典,如果要生成字典,可以使用Crunch 和 rtgen 两个工具, 一.密码生成 1.Crunch (1)启动crunch命令.执行命令如下所示. #crun ...
 - 都0202了,还在问Vegas和Pr哪个好?
			
自媒体时代,蕴藏着很多机会.许多平凡的人,通过制作视频,收获了掌声.赢得了粉丝,甚至改变了自己的命运. 图1:B站百大UP主颁奖现场 但这条路真的一路畅通吗?其实不然,他们成功的背后,必定有多方面 ...
 - ABBYY FineReader 与尚书七号OCR的对比
			
ABBYY FineReader 与尚书七号OCR都是帮助我们识别文字的工具,使用的都是OCR技术,如今文字识别工具是我们学习和工作经常会使用的,它们的功能是否实用和好用?现在通过对比的方式来探讨. ...