Word_Count(基于C++与easyx图形库)

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这两种文件。

  各个文件的关系大致如下图:

Word_Count(基于C++与easyx图形库)_第1张图片

 

 

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);
}

 

测试

   这里可用鼠标左键点击,右键是退出程序的按钮。

 Word_Count(基于C++与easyx图形库)_第2张图片

 Word_Count(基于C++与easyx图形库)_第3张图片

 

 

 Word_Count(基于C++与easyx图形库)_第4张图片

 

 Word_Count(基于C++与easyx图形库)_第5张图片

 

 

 

 

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之前要通过合理的分析,代码规范之后才能更好地对文件进行处理。

  

你可能感兴趣的:(Word_Count(基于C++与easyx图形库))