• 个人项目(C语言)


    GitHub地址:https://github.com/dachai9/personal-project.git
    1. WC 项目要求
    • 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 返回更复杂的数据(代码行 / 空行 / 注释行)。 --完成 (空行的格式控制字符只识别%d)

      • 空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
      • 代码行:本行包括多于一个字符的代码。
      • 注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
        } //注释:在这种情况下,这一行属于注释行。
    • 高级功能:
      -x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。 --未完成

    需求举例:
      wc.exe -s -a .c
    返回当前目录及子目录中所有
    .c 文件的代码行数、空行数、注释行数。

    2. PSP表格
    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划 20 10
    · Estimate · 估计这个任务需要多少时间 20 10
    Development 开发 540 985
    · Analysis · 需求分析 (包括学习新技术) 20 20
    · Design Spec · 生成设计文档 20 5
    · Design Review · 设计复审 (和同事审核设计文档) 5 20
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 15 20
    · Design · 具体设计 80 80
    · Coding · 具体编码 240 300
    · Code Review · 代码复审 60 300
    · Test · 测试(自我测试,修改代码,提交修改) 120 240
    Reporting 报告 100 180
    · Test Report · 测试报告 60 80
    · Size Measurement · 计算工作量 10 40
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 60
    合计 660 1175
    3. 解题思路
    • 需求分析:
      • 基础:需要进行文件操作,fgetc,fopen,fclose;
      • 扩展:_finddata_t handle,符号判断;
    • c语言,文件操作方法;
    • wc.exe [parameter][file_name]主函数参数;
    4. 设计实现过程:image
    5. 代码说明
    • 主函数:
    int main(int argc, char *argv[]) {
        printf("传入参数:%d
    ", argc);
        char para;//需求
        char fpara[] = "";
        char *func;//-需求
        //判断输入多少需求
        int k=0;
        for(k=1; k<=argc; k++) {
            func = argv[k];
            if(func[0] != '-') {
                break;
            }
        }
        printf("
    k: %d
    ", k);
        char *add = argv[k];
    
        for(int j=k; j<argc; j++) {
            add = argv[j];
            for(int i=1; i<k; i++) {
                func = argv[i];
                para = func[1];
    
                switch(para) {
                case 's':
                    printf("
    ");
                    recursion(add);
                    break;
                case 'a':
                    justify(add);
                    break;
                case 'l':
                    countLines(add);
                    break;
                case 'w':
                    countWords(add);
                    break;
                case 'c':
                    countChars(add);
                    break;
                default:
                    break;
                }
            }
        }
    }
    
    • 行数统计
    int countLines(char *fileName) {
        FILE *fp;
        fp = fopen(fileName, "r");
        char ch;
        int cl = 0;
    
        if(fp == NULL) {
            printf("打开文件失败!
    ");
        } else {
            ch = fgetc(fp);
            if(ch == EOF) {
                printf("行数:0
    ");
                return 0;
            }
            while(ch != EOF) {
                if(ch != '
    ') {
                    ch = fgetc(fp);
                } else {
                    cl++;
                    ch = fgetc(fp);
                }
            }
            printf("行数:%d
    ", ++cl);
        }
    
        fclose(fp);
        return cl;
    }
    
    • 单词数统计
    int countWords(char *fileName) {
        FILE *fp;
        fp = fopen(fileName, "r");
        char ch;
        int cw = 0;
        int word = 0;
    
        if(fp == NULL) {
            printf("打开文件失败!
    ");
        } else {
            ch = fgetc(fp);
            if(ch == EOF) {
                printf("单词数:0
    ");
                return 0;
            }
            while(ch != EOF) {
                /*if(ch != ' ' && ch != '
    ') {
                    //putchar(ch);
                    ch = fgetc(fp);
                }else {
                    cw++;
                    //printf("单词数:%d
    ", cw);
                    ch = fgetc(fp);
                }*/
                if((ch == ' ' || ch == '
    ') && word == 1) {
                    word = 0;
                    cw+=1;
                } else if(((ch >= 'a' && ch <= 'z') || ch >= 'A' && ch <='Z') && word == 0) {
                    word = 1;
                }
                //printf("%c", ch);
                ch = fgetc(fp);
            }
            if(word == 1) cw++;
            printf("单词数:%d
    ", cw);
        }
    
        fclose(fp);
        return cw;
    }
    
    • 字符数统计
    int countChars(char *fileName) {
        FILE *fp;
        fp = fopen(fileName, "r");
        int cc = 0;
        char ch;
    
        if(fp != NULL) {
            ch = fgetc(fp);
            while(ch != EOF) {
                if(ch != '
    ') {
                    cc++;
                    ch = fgetc(fp);
                } else {
                    ch = fgetc(fp);
                }
            }
            printf("字数:%d
    ", cc);
        } else {
            printf("打开文件失败!
    ");
        }
    
        fclose(fp);
        return cc;
    }
    
    • 遍历文件(函数本身可处理.c,但由于传入参数如果是.c,代表一个一个文件传入,所以这里函数作用不明显)
    int recursion(char *fpara) {
        long handle;//用于查找的句柄
        struct _finddata_t fileinfo;//文件信息的结构体
        handle = _findfirst(fpara, &fileinfo);
        if(-1 == handle) {
            printf("查找失败!");
            system("pause");
            return -1;
        }
        printf("%s
    ", fileinfo.name);
        while(!_findnext(handle, &fileinfo)) {
            printf("%s
    ", fileinfo.name);
        }
        _findclose(handle);
        return 0;
    }
    
    • 特殊行判断(其中的zs_f 是判断是否出现/*)
    int justify(char *fileName) {
        FILE *fp;
        fp = fopen(fileName, "r");
        if(NULL == fp) {
            printf("打开文件失败!");
            system("pause");
            return 0;
        }
        int zs_f = 0;
        char ch_fp, ch_next;//ch_next:下一个字符
        int k=0, d=0, z=0, f=0;//k: 空行 d:代码行 z:注释行 f:是否顶格
        ch_fp = fgetc(fp);
        ch_next = fgetc(fp);
        while(ch_fp != EOF) {
            if(ch_fp == ' ' || ch_fp == '}' || ch_fp == '{') {
                ch_fp = ch_next;
                ch_next = fgetc(fp);
            } else {
                if((ch_fp == '
    ') && f == 0) {
                    k++;
                } else if(ch_fp == '/' && ch_next == '/' && f == 0) {
                    z++;
                } else if(ch_fp == '/' && ch_next == '*' && f == 0) {
                    z++;
                    zs_f = 1;
                }
                if(zs_f == 1) {
                    while(ch_fp != '*' || ch_next != '/') {
                        if(ch_fp == '
    ') {
                            z++;
                        }
                        ch_fp = ch_next;
                        ch_next = fgetc(fp);
                    }
                    zs_f = 0;
                }
    
                ch_fp = ch_next;
                ch_next = fgetc(fp);
                if(ch_fp == '{' || ch_fp == '}') {
                    ch_fp = ch_next;
                    ch_next = fgetc(fp);
                }
                if(f == 0) {
                    f = 1;
                    if(ch_next == ' ') {
                        f = 0;
                    }
                }
                if(f == 2) {
                    if(ch_fp == '
    ') {
                        k++;
                    }
                    f=0;
                }
                if(ch_fp == '
    ') {
                    f = 2;
                    if(ch_next == '
    ')
                        f=0;
                    if(ch_next == EOF)
                        k++;
                }
            }
        }
        d = countLines(fileName) - k - z;
        printf("
    空格行:%d
    代码行:%d
    注释行:%d
    ", k, d, z);
    
        printf("文档结束!
    ");
        return 0;
    }
    
    测试运行
    • 基础部分:

    • 扩展部分:image

    • 错误参数:

      文件路径输入错误
      image

      无操作输入

    项目小结

    对GitHub的使用还不熟练;学了新的知识:_finddata_t;提高了逻辑思维能力(特殊行判断);学会控制情绪。
    花了这么长时间,说到底还是太菜,没有好好理清思路就上手,所以做好设计文档还是蛮重要的。
    非常喜欢PSP,觉得这个计划表可以能鞭策自己再加努力,不管是对项目需求的分析分解还是对自己编程能力的提高。
    还有就是自己预计的时间跟最终的时间相差了将近8小时!!!太夸张了。还是要充分了解需求才能好好估算时间。

  • 相关阅读:
    linux shell dash&bash(转)
    GNU Linux Boot ID Machine ID
    MAC地址对照表
    设备树中的spi设备以及内核对spi节点的处理流程(转)
    CRC32 逆向算法的C语言实现(转)
    ZYNQ7045 系统升级实现方法(multiboot)(转)
    echarts 如果打开多个页面直折线图不展示,及echarts和radio-group的结合使用
    Openwrt SSH免密码登录linux服务器
    让windows10支持多用户连接
    打印SQL日志
  • 原文地址:https://www.cnblogs.com/dachai/p/12559314.html
Copyright © 2020-2023  润新知