Word_Count(基于C++与easyx图形库)
Github : Github
EasyX : https://easyx.cn/
简介
-
此项目实现一个简单而完整的统计工具。
-
- 需要此程序需从GitHub上下载,需统计代码的文件需要置放于Debug中的WC_Test文件中。
需求
-
统计文本文件的字符数、单词数和行数
拓展
-
递归处理目录下符合条件的文件,返回代码行、空行、注释行。
-
空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
-
代码行:本行包括多于一个字符的代码。
-
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释: } //注释
高级功能
刚看到题目的时候,觉得题目本身不会很难,但是要选择什么语言与框架进行书写? 由于之前没有学过C++跟easyx,本着多学点东西,就选择了c++进行书写,先花了大概两个多小时的时间进行C++的熟悉,之后就进行代码思路上的分层。
设计思路
代码应该可以大致分成两个类,一个是文件IO处理,一个是图形界面,这里用的是easyx,一个比较简单基础的图形库。拿IO处理来说,应该有一个函数是可以输出文件夹的内容的,假设我们把这些内容存在数组中,那么View则有一个函数可以把数组放到图形界面上,这样一一对应,使用接口化编程,使得界面跟io处理的两个类可以较好的分离开来,这样使得main函数中的内容不会太乱以至于浪费额外的debug时间。 代码的测试使用的是自己写好的文件,有txt、cpp这两种文件。
各个文件的关系大致如下图:

Code
- 代码托管于github上,这里只做部分说明。
main
首先是main函数,接口化让main函数变得比较轻便
// 初始化图形窗口 initgraph(640, 480); FileIo F; FileIo_View V; string Path = "WC_Test"; vector<string> Fio_Files; MOUSEMSG Mou; // 定义鼠标消息 F.Get_Fio_Files(Path, Fio_Files);//得到路径下的文件 V.Fio_File_Out(Fio_Files); //显示文件 do{ Mou = GetMouseMsg(); if (Mou.uMsg == WM_LBUTTONDOWN){ if (Mou.x >= 220 && Mou.x <= 440){ int i = V.Fio_File_ID(Mou.x, Mou.y, Fio_Files.size()); if (i == -1){ continue; } cleardevice();//刷新一次 略等于那个system(cls) F.Total_Fio_CPP(Fio_Files[i]); F.Total_Fio_CWL(Fio_Files[i]); V.Fio_Total_Out(1,F); _getch(); FlushMouseMsgBuffer();//清除鼠标缓存 cleardevice(); V.Fio_File_Out(Fio_Files); } } else if(Mou.uMsg == WM_RBUTTONDOWN){ closegraph(); return 0; } }while (true);
统计行数、字符数、单词数
此函数统计出行数、字符数、总单词数,之前想着一个一个字符录入,但是发现不太行,又采用了buffer方法。
1 Fio_Lines_Sum = 0; // 总行数 2 Fio_Chars_Sum = 0; // 总字符数 3 Fio_Words_Sum = 0; // 总单词数 4 5 char buffer[256]; 6 int bufferLen = 0; 7 int isLastBlank = 0; 8 int WordNum = 0; 9 int CharNum = 0; 10 11 while (!Fio_Fin.eof()){ 12 13 Fio_Fin.getline(buffer, 256,'\n'); 14 bufferLen = strlen(buffer); 15 16 //printf("%d\n", bufferLen); 17 // 遍历缓冲区的内容 18 for (int i = 0; i < bufferLen; i++){ 19 20 char ch = buffer[i]; 21 if (ch == ' ' || ch == '\t'){ 22 23 if (!isLastBlank){ 24 WordNum++; 25 } 26 isLastBlank = 1; 27 } 28 else if (ch != '\n' && ch != '\r'){ 29 CharNum++; 30 isLastBlank = 0; 31 } 32 } 33 34 if (!isLastBlank){ 35 WordNum++; 36 } 37 38 isLastBlank = 1; 39 40 41 Fio_Lines_Sum++; // 总行数 42 Fio_Chars_Sum += CharNum; // 总字符数 43 Fio_Words_Sum += WordNum; // 总单词数 44 45 CharNum = 0; 46 WordNum = 0; 47 }
处理单行注释
外套一个检查是否处理到文件尾的循环即可
1 2 //“//注释行” 3 if (!Fio_Xgx && Fio_Line[i] == '/' && Fio_Line[i + 1] == '/'){ 4 5 if (Fio_Code){ //“前有代码” 6 ++Num_Zs; //注释 7 ++Num_Dm; //代码 8 } 9 else 10 { 11 ++Num_Zs; 12 } 13 break; //跳出当前行(即,内while循环) 14 }
处理多行注释
其他的部分跟多行注释都差不多,最主要的是要知道当 有双引号的时候,是得跳过双引号中的//的,避免对双引号中的内容进行读取进入注释,读到
1 //“/*注释开始” Fio_Xgx是出现 /*的标志 2 if (!Fio_Xgx && Fio_Line[i] == '/' && Fio_Line[i + 1] == '*'){ 3 i += 2; //跳过/*符号 4 Fio_Xgx = 1; //“/*”开始 5 Fio_Zs = 1; 6 continue; 7 } 8 9 //“多行注释” 10 if (Fio_Xgx){ 11 //“*/注释结束” 12 if (Fio_Line[i] == '*' && Fio_Line[i + 1] == '/'){ 13 ++i; //“跳过*/” 14 Fio_Xgx = 0; 15 } 16 else if (Fio_Line[i] == '\0') //行末尾 17 { 18 if (Fio_Code) //如果前面有代码 19 { 20 ++Num_Dm; 21 ++Num_Zs; 22 } 23 else 24 { 25 ++Num_Zs; 26 } 27 break; 28 } 29 ++i; 30 continue; 31 } 32 if (Fio_Line[i] == '\0') 33 { 34 if (Fio_Zs){ 35 ++Num_Zs; 36 } 37 if (Fio_Code){ 38 ++Num_Dm; 39 } 40 break; 41 }
View的一个输出函数
函数用于输出File文件下的目录,这里是WC_Test中的文件
void FileIo_View::Fio_File_Out(vector<string>Fio_Files){ int x = this->Img_X; int y = this->Img_Y; for (int i = 0; i < Fio_Files.size(); i++){ string One_File = Fio_Files[i]; char *szWord = new char[One_File.length() + 1]; TCHAR tszWord[1024] = { 0 }; strcpy(szWord, One_File.c_str()); #ifdef UNICODE MultiByteToWideChar(CP_ACP, 0, szWord, -1, tszWord, 1024); #else strcpy(tszWord, szWord); #endif fillrectangle(240, y, 500, y + 20); outtextxy(x + 10, y + 3, tszWord); y += 40; } TCHAR OutT[255]; _stprintf(OutT, _T("鼠标右键退出...")); outtextxy(x + 10, y + 3, OutT); }
测试
这里可用鼠标左键点击,右键是退出程序的按钮。




PSP
|
PSP2.1 |
Personal Software Process Stages |
预估耗时(分钟) |
实际耗时(分钟) |
|
· Planning |
· 计划 |
30 |
30 |
|
· Estimate |
· 估计这个任务需要多少时间 |
500 |
600 |
|
· Development |
· 开发 |
300 |
300 |
|
· Analysis |
· 需求分析 (包括学习新技术) |
200 |
150 |
|
· Design Spec |
· 生成设计文档 |
20 |
40 |
|
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
15 |
|
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
5 |
5 |
|
· Design |
· 具体设计 |
30 |
25 |
|
· Coding |
· 具体编码 |
200 |
300 |
|
· Code Review |
· 代码复审 |
100 |
150 |
|
· Test |
· 测试(自我测试,修改代码,提交修改) |
100 |
100 |
|
· Reporting |
· 报告 |
40 |
60 |
|
· Test Report |
· 测试报告 |
30 |
50 |
|
· Size Measurement |
· 计算工作量 |
15 |
20 |
|
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
15 |
30 |
|
· 合计 |
|
1595 |
1875 |
总结
- 项目不难,但是值得迭代,接下来还有许许多多的想法,如多线程读取文件、图形界面输出文件根目录等等..
- 其实写代码最麻烦的事情是debug,在debug之前要通过合理的分析,代码规范之后才能更好地对文件进行处理。
浙公网安备 33010602011771号