zoukankan      html  css  js  c++  java
  • 个人项目 源程序特征统计程序(C++)

    零、GitHub地址

    https://github.com/King-Authur/Word-count


    一、项目的相关要求

    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 文件的代码行数、空行数、注释行数。


    简化后的要求
    基本功能
    支持 -c
    支持 -w
    支持 -l

    扩展功能
    支持 -s 参数
    支持 -a 参数
    支持各种文件的通配符(*,?)

    高级功能
    基本的Windows GUI 程序操作
    支持通过图形界面选取文件
    支持通过图形界面展现文件的信息


    二、遇到的困难和解决方法

    (一)如何使用命令行运行程序
    查阅相关资料后,总结了知识点和方法,并写了一遍博客
    博客链接

    (二)如何实现基础功能
    首先定好判断的标准

    字符:字母、计算机字符
    单词:由一个或一个以上的连续字母所构成的字符串
    行:空行与非空行的总和
    代码行:非空行且非注释行
    空行:由空格、回车、tab、} 构成的行
    注释行:含有 \ 并且它不被包含在两个双引号中

    思路是,按照该标准一步一步实现代码,计算出结果即可。

    (三)如何递归查询文件夹 以及 通配符 ?和 * 如何实现**
    这两个功能可以一起实现。
    关于这部分,我查阅相关资料后总结了知识点和方法,并写了一遍博客
    博客链接

    递归文件夹部分使用_findfirst();和_findnext();函数实现的。

    至于通配符,因为cmd输入带有通配符的文件路径作为参数时,会自动完成对文件路径的通配符补充,所以无法通过用cmd运行来验证通配符功能是否实现。
    但是由于通配符是用_findfirst();和_findnext()函数实现的,程序中的代码经过严格调试,可以认为无误,逻辑上通配符功能是实现了的。

    思路上:对于传入的文件路径,例如:D:c++WC*.cpp

    会把它拆成两部分 D:c++WC 和 *.cpp
    递归D:c++WC下的所有文件夹,在当前目录的所有文件夹都遍历后,对当前目录下非文件的文件进行通配符 *.cpp的匹配,计算信息后,输出各个匹配成功的文件的结果。

    (四)图形界面的实现
    能够弹出简单的图形界面

    (五)错误输入的检验
    有判断文件是否存在,路径是否正确,在输入错误的文件路径后,会报错并终止程序。

    (六)正则表达式的判断
    没有实现,待更新。


    三、关键代码 和 设计说明

    设计图
    采用了面向过程的设计
    在这里插入图片描述
    目前实现了以下几个函数

    void get_flag(int argc, char **argv);
    void calculate_information(char *file_path);
    bool is_char(char ch);
    void display();
    
    

    关键代码
    1、void calculate_information(char *file_path);
    该函数用于计算出所有题目中要我们求的数据,包括字符、单词、行、代码行、空行、注释行的数目。

    void calculate_information(char *file_path){
        FILE* fp = fopen(file_path, "r");//只读打开文件路径指向的文件
        if(fp == NULL){//检测是否是有效路径
            printf("!!!错误!!!
    请检查文件路径是否正确
    ");
            exit(-1);//关闭程序
        }
        char buffer[maxn_word_of_line];//存取当前行数据的缓存区
        while(!feof(fp))//是否到文件尾
        {
            buffer[0] = '';
            fgets(buffer, maxn_word_of_line, fp);//一整行读取
            res.line++;
    
            int len = strlen(buffer);
            bool left_blank = true, is_Empty = true;
            for(int i = 0; i < len; i++)
            {
               if(is_char(buffer[i]))///如果是非空字符
                {
                    res.character++;///那么字符数要增加
                    is_Empty = false;///并且这一行不为空
                }
    
                if(isalpha(buffer[i]))///当它是字母时
                {
                    if(left_blank)///当左边被其他字符隔开时
                    {
                        res.word++;///单词数目+1
                        left_blank = false;
                    }
                }
                else///当前字符不是字母
                {
                    left_blank = true;///则视为它是隔开单词的字符
                }
            }
            if(is_Empty)///这一行为空行
            {
                res.empty_line++;
            }
            else///这一行非空,判断一下是否为注释行
            {
                bool left_quote = false;///左双引号
                bool slanting_bar = false;///斜杆
                bool explain_flag = false;///注释行的标记
                ///过滤掉包含于字符串输出的“假注释”,例如:printf("//");
                for(int i = 0; i < len; i++)
                {
                    if(buffer[i] == '"')///如果是双引号
                    {
                        if(!left_quote)///如果没有左边匹配的双引号
                        {
                            left_quote = true;
                        }
                        else
                        {
                            left_quote = false;///左边有可以匹配的双引号
                        }
                    }
    
                    if(buffer[i] == '/' && buffer[i + 1] == '/')///如果有连续的两个反斜杠
                    {
                        slanting_bar = true;
                    }
    
                    if(!left_quote && slanting_bar)///如果斜杠没有被包含在字符串的输出中,则这一行必定为注释行
                    {
                        res.explain_line++;
                        explain_flag = true;
                        break;
                    }
                }
                if(!explain_flag)///不是注释行,就是代码行
                {
                    res.code_line++;
                }
            }
        }
    }
    

    该函数会逐行读取整个文件,每行遍历两次即可计算出改行的所有信息,信息存放在结构体内,不断更新直到读取到文件尾。
    输出时根据传入的参数决定输出哪些内容。

    2、````


    四、测试运行

    基础部分与扩展部分中的 -a 一起测试
    1、测试只有两行空白行的文件
    在这里插入图片描述
    无误

    2、测试只含有两个单词、十个字符的文件
    在这里插入图片描述
    无误

    3、测试一份简单的代码
    在这里插入图片描述
    检验可知
    printf("\");没有被误认为注释行
    printf("Hello world ");//Hello world}//注释正确的被识别为注释行
    其他数据的结果也无误

    测试文件路径
    4、输入错误的文件路径
    在这里插入图片描述
    会有错误提示

    5、递归文件夹功能
    在这里插入图片描述
    可以看到,在输入的文件目录下的 main.cpp 和 该目录的bin文件下的 main.cpp这两个同名的文件(内部代码不同)都输出了信息,递归功能无误。


    五、PSP表格

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

    六、项目小结

    1、不熟悉面向对象编程,只使用了面向过程编程
    2、没有识别/**/注释的代码
    3、递归文件夹下的文件 和 图形界面 功能尚未完成
    4、提交时GitHub网页炸了
    5、代码实现和测试时出现了一些小错误,导致花费了更多的时间
    6、还在学习Windows 编程
    7、后续还会继续更新和完善
    8、一开始设计时,因为过多的考虑了效率上的问题,而没有让结果有足够高的精准度。


    七、参考来源

    [1] 软件工程个人项目作业
    [2] 项目博客模板
    [3] 《构建之法》
    [4] VS2015安装与C++进行简单单元测试
    [5] C++利用 _findfirst与_findnext查找文件的方法

  • 相关阅读:
    Educational Codeforces Round 49 (Rated for Div. 2)
    Codeforces Round #506 (Div. 3)
    multiset
    C++中substr函数的用法
    7.30 背包问题
    7.29 dp动态规划
    7.27 图论 存图 前向星 最短路 dijstra算法 SPFA算法
    7.26 搜索进阶(状压搜索,迭代加深搜索)
    7.23 深搜广搜
    7.24 二分搜索
  • 原文地址:https://www.cnblogs.com/Authur-gyc/p/12563500.html
Copyright © 2011-2022 走看看