zoukankan      html  css  js  c++  java
  • 个人项目作业

    一、github地址

    https://github.com/Chendabaiiii/wordCounter

    二、PSP表格(估计)

     PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟)

     Planning

     计划

     30

     Estimate

     估计这个任务需要多少时间

     30

     Development

     开发

     1440

     Analysis

     需求分析 (包括学习新技术)

     120

     Design Spec

     生成设计文档

     60

     Design Review

     设计复审 (和同事审核设计文档)

     30

     Coding Standard

     代码规范 (为目前的开发制定合适的规范)

     30

     Design

     具体设计

     60

     Coding

     具体编码

     1000

     Code Review

     代码复审

     60

     Test

     测试(自我测试,修改代码,提交修改)

     30

     Reporting

     报告

     60

     Test Report

     测试报告

     40

     Size Measurement

     计算工作量

     30

     Postmortem & Process Improvement Plan

     事后总结, 并提出过程改进计划

     60

     合计

     3080

    三、解题思路

    1. 编程语言的选择

    一开始注意到此软件是一个命令行程序,可能需要用到 cmd 命令行传参来运行,之前学C语言时并没有了解过此类方法。自己本身的技术栈也只是页面上的开发,并没有学过利用前端三剑客开发桌面应用的相关技术。后来了解了一项可以结合HTML、CSS、JS开发桌面应用的Electron技术后,又想起有个遍历文件/选择文件的功能,这个时候js可能没有优势,想到可能会踩很多坑,于是决定用C++/C作为技术栈边学边用开发此软件。

    四、设计实现过程

    1. 代码的组织

    首先我把主函数文件和工具函数分开,在主函数进行工具函数的调用;

    工具函数中的核心函数有:

    int getWordNumInLine(char* str);    // 计算单行单词个数
    void trim(string& str);          // 去除字符串的头尾空格
    void characterCount(string fileName);   // 计算字符个数
    void wordCount(string fileName);         // 计算单词个数
    void lineCount(string fileName);           // 记算行数
    void complexLineCount(string fileName);    // 返回更复杂的数据(代码行 / 空行 / 注释行)
    bool judgeComment(string line, bool& isInComment);   // 判断是不是在注释行内

    五、代码说明

    getWordNumInLine

    // 计算文件的字符个数
    void characterCount(string fileName) {
        int charNum = 0;        // 记录字符数目
        char line[256];
        fstream file;                // 文件流
        file.open(fileName, ios::in);            // 采用读取方式打开文件
        while (!file.eof())
        {
            file.getline(line, 256, '
    ');    // 该行字符达到256个或遇到换行就结束
            int len = strlen(line);
            charNum += len;
            for (int i = 0; i < len; i++) {
                // 如果是中文则要减1,因为中文算是双字节
                if (line[i] < 0 && line[i + 1] < 0) {  
                    charNum--;
                    i++;
                }  
            }
        }
        file.close();
        cout << "该文件共有" << charNum << "个字符" << endl;
    };

    characterCount

    // 计算单行单词个数
    int getWordNumInLine(char* str) {
        int cnt = 0, i = 0;
        int len = strlen(str);
        for (i = 0; i < len - 1; i++) {
            // 字母 + 非字母 则为一个单词的结束
            if (isalpha(str[i]) && (!isalpha(str[i + 1]))) cnt++;
        }
        // 以两个字母结束的情况
        if (isalpha(str[i])) cnt++;
        return cnt;
    }

    wordCount

    // 计算文件的单词个数
    void wordCount(string fileName) {
        int wordNum = 0;        // 记录单词数目
        char line[256];
        fstream file;                // 文件流
        file.open(fileName, ios::in);            // 采用读取方式打开文件
        while (!file.eof())
        {
            file.getline(line, 256, '
    ');    // 该行字符达到256个或遇到换行就结束
            wordNum += getWordNumInLine(line);
        }
        file.close();
        cout << "该文件共有" << wordNum << "个单词" << endl;
    }

    lineCount

    // 计算文件的行数
    void lineCount(string fileName) {
        int lineNum = 0;        // 记录行数目
        char line[256];
        fstream file;                // 文件流
        file.open(fileName, ios::in);            // 采用读取方式打开文件
        while (!file.eof())
        {
            file.getline(line, 256, '
    ');    // 该行字符达到256个或遇到换行就结束
            lineNum++;
        }
        file.close();
        cout << "该文件共有" << lineNum << "" << endl;
    }

    judgeComment

    // 判断是不是在注释内
    // 返回true表示该行是注释行
    bool judgeComment(string line, bool& isInComment) {
        regex pattern1("^[{}]?[\s]*\/\/[^\n]*");  // 为"//"、"{...//"、"}...//"的行级注释
        regex pattern2("^\*\/[//s]*[{}]?$");                // 为"*/"、"*/...{"、"*/...}"
        regex pattern3("\/\*[^\*^\/]*\*\/");            // 匹配 /**/
        regex pattern4("^[{}]?[//s]*\/\*[^\n]*");    // 匹配 "/*..."、"{/*..."、"}/*..."
        if (regex_match(line, pattern1)) return true;        // 是行级注释
        if (regex_match(line, pattern2)) {
            isInComment = false;  // 没在注释内但是该行算注释
            return true;                    
        } 
        // 如果在注释内,而且该行找不到 */ 块注释结束行
        if (isInComment && line.find("*/") == string::npos) {
            return true; 
        }
        string replaceStr = regex_replace(line, pattern3, "");  // 去除字符串中所有 /**/对
        if (regex_match(replaceStr, pattern4)) {
            isInComment = true;
            return true;
        }
        return false;
    }

    complexLineCount

    // 返回更复杂的数据(代码行 / 空行 / 注释行)
    void complexLineCount(string fileName) {
        int codeLine = 0,                        // 代码行
                emptyLine = 0,                    // 空行
                commentLine = 0;                // 注释行
        bool isInComment = false;      // 是否在注释块里
        bool isEmptyLine = false;        // 是否是空行的标志
        regex isEmpty("^[{}]?$");   // 是否是空行的正则
        char line[256];
        fstream file;                // 文件流
        file.open(fileName, ios::in);            // 采用读取方式打开文件
        while (!file.eof())
        {
            isEmptyLine = false;
            file.getline(line, 256, '
    ');    // 该行字符达到256个或遇到换行就结束
            int len = strlen(line);
            string strLine(line);       // 将char数组转为string
            trim(strLine);
            // 注释块里面的空行不包括
            if (!isInComment && regex_match(line, isEmpty)) {
                emptyLine++;    // 不在注释块内且长度小于1则为空行
                isEmptyLine = true;
            } 
            // 如果是注释行
            if (judgeComment(strLine, isInComment)) {
                commentLine++;
            } else if(!isEmptyLine){
                // 如果不是注释行而且不是空行,那就是代码行
                codeLine++;
            }
        }
        file.close();
        cout << "该文件共有" << endl << codeLine << "代码行" << endl << emptyLine << "空行" << endl << commentLine << "注释行" << endl;
    }

    main方法

    // 主函数
    // argc 是命令参数数目
    // argv 接收命令参数字符串, argv[0] 默认为exe文件路径
    int main(int argc, char** argv)
    {
        if (argc < 3) {
            cout << "参数有误,请输入正确的参数" << endl;
            return 0;
        }
        // 需要外传入两个参数,一个是模式,一个是文件名
        string mode = argv[1];
        string fileName = argv[2];
        setlocale(LC_ALL, "chs");
        switch (mode[1]) {
            // 字符计数
            case 'c': {
                characterCount(fileName);        
                break;
            }
            // 单词计数
            case 'w': {
                wordCount(fileName);                
                break;
            }
            // 行数
            case 'l': {
                lineCount(fileName);                
                break;
            }
            // 返回更复杂的数据(代码行 / 空行 / 注释行)
            case 'a': {    
                complexLineCount(fileName);
                break;
            }
            default: {
                break;
            }
        }
        return 0;
    }

    六、测试运行

    功能实现:本程序只实现了 -c、-w、-l、-a的功能指令

    测试使用样例

    int a;//what
    /**/int b;
    
    // 6
    void test() {
    
      for (;;) {
      }
    
    } // aaaaa
    /*
    */

    测试结果

    -c(计算字符数)

     -w(计算单词数)

     -l(计算行数)

     -a(复杂行数计算)

    七、PSP表格(实际)

     

     PSP2.1

    Personal Software Process Stages

    预估耗时(分钟)

    实际耗时(分钟)

     Planning

     计划

     30

     20

     Estimate

     估计这个任务需要多少时间

     30

     20

     Development

     开发

     1440

     780

     Analysis

     需求分析 (包括学习新技术)

     120

     200

     Design Spec

     生成设计文档

     60

     0

     Design Review

     设计复审 (和同事审核设计文档)

     30

     20

     Coding Standard

     代码规范 (为目前的开发制定合适的规范)

     30

     20

     Design

     具体设计

     60

     10

     Coding

     具体编码

     1000

     780

     Code Review

     代码复审

     60

     60

     Test

     测试(自我测试,修改代码,提交修改)

     30

     60

     Reporting

     报告

     60

     60

     Test Report

     测试报告

     40

    20

     Size Measurement

     计算工作量

     30

     30

     Postmortem & Process Improvement Plan

     事后总结, 并提出过程改进计划

     60

     20

     合计

     3080

     2100



    八、项目小结

    第一次使用c语言开发一个小小小程序,有很多做的不好的地方。code review之后觉得自己的代码封装性不强,代码覆盖率不高,唯有仅仅将功能函数与主函数进行分离。

    由于以前很少接触书本以外的API,要实现一些功能需要查阅好些资料。此次遇到比较大的困难是注释行的计算,由于思考过后发现将会有很多的情况,于是后来考虑使用正则表达式来匹配,但由于正则接触的不多,平时也比较少使用,基本上就忘了,经过这个功能的实现,也相当于重温了一下正则表达式。也经过了这次项目的开发,发现自己技术上还有太多太多的缺陷。由于技术的限制、其他不可抗力因素以及自己的拖延症,而导致最终只能实现这几个小小的功能。

    也让我清楚的知道了自己的编程之路还很长,于是我将反思后在下个项目付出更多的努力!

     

  • 相关阅读:
    windows7 下的日期没有internet时间的选项卡
    Oracle SQL性能优化的40条军规
    BOS中定区关联客户
    远程调用——hessian使用入门
    使用apache POI解析Excel文件
    jQuery OCUpload ——> 一键上传插件
    SSH——增删改的实现二
    SSH——增删改的实现一
    SSH——基于datagrid实现分页查询
    (五)EasyUI使用——datagrid数据表格
  • 原文地址:https://www.cnblogs.com/Chendabaiiii/p/12501206.html
Copyright © 2011-2022 走看看