WordCount程序(C语言)

Github地址:https://github.com/peter-ye-code/WordCount

一、题目描述

  • 实现一个简单而完整的软件工具(源程序特征统计程序)。
  • 进行单元测试、回归测试、效能测试,在实现上述程序的过程中使用相关的工具。
  • 进行个人软件过程(PSP)的实践,逐步记录自己在每个软件工程环节花费的时间。

二、PSP表格

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

三、思路

  1. 刚开始拿到题目,就决定用C语言去做这个项目,因为自己学习的高级语言只有C和JavaScript,对于C语言的话更有把握一些。
  2. 在开始着手做这个项目时,我先通过网上资源得知这个项目的关键知识点是对文件的操作,如fgetc和fgets函数,于是就花了一些时间在文件操作的学习上。
  3. 在学习完相关文件操作后,就开始进行相关模块的开发,之后再汇总成一个大模块

四、设计实现过程

1、根据需求来分的话,该项目可分为6个函数,分别为

  • 主函数
  • 统计字符的函数
  • 统计单词的函数
  • 统计行数的函数
  • 统计空行/注释行/代码行的函数
  • 递归处理目录的函数

2、之后在具体敲代码过程中,我又把统计空行/注释行/代码行的函数划分为

  • 统计空行的函数
  • 统计单行和多行注释的函数
  • 统计其他注释行(在单字符后面加注释的情况)

3、主函数的逻辑框图如下

五、代码说明

  • 返回文件字符数

    • fgetc函数,逐个读入字符,如果满足条件,字符数增加
    //统计文件字符数
    int getChar(FILE *fp){
    char ch;
    int number=0;
    while((ch=fgetc(fp))!=EOF){//读取不到字符会显示EOF
    if((ch!='\n')&&(ch!=' ')&&(ch!='\t')){
    number++;
    }
    }
    rewind(fp);
    return number;
    }
  • 返回文件单词数

    • fgetc函数,逐个读入字符,如果满足条件,单词数增加
    //统计文件单词数
    int getWord(FILE *fp){
    int flag=0;
    int number=0;
    char ch;
    while(feof(fp)==0)//等于0表示文件未结束
    {
    ch = fgetc(fp);//读取一个字符后,光标位置会后移一个字节继续读
    if((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')
    ||(ch >= '0' && ch <= '9')){
    flag = 0;
    }
    else if(flag == 0 && (ch != '-' && ch != '/'&& ch != '\'')) //ch不是字母和数字
    {
    number++;
    flag = 1;
    }
    }
    rewind(fp);
    return number;
    }
  • 返回文件行数

    • fgetc函数,逐个读入字符,判断是否为换行符,若有换行符,文件行数增加
    //返回文件行数
    int getLine(FILE *fp){
    char ch;
    int number=0;
    while(feof(fp)==0)//等于0表示文件未结束
    {
    ch = fgetc(fp);//读取一个字符后,光标位置会后移一个字节继续读
    if(ch=='\n'){//如果是换行符
    number++;
    }
    }
    rewind(fp);
    return number+1;
    }
  • 显示空行/注释行/代码行

    • fgets函数,读入文件的一整行到数组中,对数组进行遍历操作。
    //统计空行
    int getnull_line(FILE *fp){
    int null_line = 0;
    int bufsize = 100;
    char buf[bufsize] = {0};
    while(feof(fp)==0){
    //遍历文件的每一行
    fgets(buf,bufsize,fp);
    if(buf[0]=='\n'){
    null_line++;
    }
    }
    rewind(fp);
    return null_line;
    } //统计其他注释行
    int getother_line(FILE *fp){
    int line;
    bool is_annotation_line=false;
    fp = fopen("file.txt","r");
    while(feof(fp)==0){
    char buf[100] = {0};
    fgets(buf,100,fp);
    int len=strlen(buf);
    for(int i=0;i<len;i++){
    if (buf[i]!='/')
    {
    if ((i+2<len) && (buf[i+1]=='/')&&(buf[i+2]=='/'))
    is_annotation_line=true;
    break;
    }
    }
    if (is_annotation_line==true) line++;
    }
    rewind(fp);
    return line;
    } //统计注释行和代码行
    int getcomplex_data(FILE *fp,int &annotion_line,int &code_line){
    int sigle_annotion_line = 0;
    int bufsize = 100;
    char buf[bufsize] = {0};
    int flag = 0;
    int multi_annotion_line=0;
    while(feof(fp)==0){
    fgets(buf,bufsize,fp);
    if(buf[0]=='/'&&buf[1]=='/'){
    sigle_annotion_line++;
    }else if(flag == 0){
    if(buf[0]=='/'&&buf[1]=='*'){
    multi_annotion_line++;
    flag=1;
    }
    }else if(flag == 1){
    if(buf[0]!='*'&&buf[1]!='/'){
    multi_annotion_line++;
    }else if(buf[0]=='*'&&buf[1]=='/'){
    multi_annotion_line++;
    flag=0;
    }
    }
    }
    rewind(fp);//在调用一个函数需将文件指针调整回开头
    int other_annotion_line = getother_line(fp);
    annotion_line = sigle_annotion_line+multi_annotion_line+other_annotion_line;
    int line = getLine(fp);
    int null_line = getnull_line(fp);
    code_line = line - annotion_line - null_line;
    }
  • 递归处理目录

    • 使用_findfirst函数进行查找相关的txt文件,另外用_findnext进行下一个文件的查找
    //处理目录下符合条件的文件
    int handle_file(){
    struct _finddata_t fileinfo; //文件存储信息结构体
    long file_handle; //文件句柄
    file_handle = _findfirst("*.txt",&fileinfo); //查找当前目录下的txt文件
    FILE *fp;
    int a,b;
    if(file_handle==-1)
    printf( "当前目录下没有txt文件\n");
    else
    do{//先找第一个再找下一个
    fp=fopen(fileinfo.name,"r");
    printf("找到文件%s\n",fileinfo.name);
    printf("字符数为%d\n",getChar(fp));
    printf("词数为%d\n",getWord(fp));
    printf("行数为%d\n",getLine(fp));
    printf("空行数为%d\n",getnull_line(fp));
    getcomplex_data(fp,a,b);
    printf("注释行数为%d\n",a);
    printf("代码行数为%d\n\n",b);
    }while(_findnext(file_handle,&fileinfo)==0);//找到下一个
    _findclose(file_handle); //关闭文件链接
    }
  • 主函数

    int main(int argc,char*argv[]){
    FILE *fp;
    int number;
    char string; if(argc==3){
    //读取文件的内容
    fp = fopen(argv[2],"r")
    //打开失败
    if(fp == NULL){
    printf("错误:无法打开%s\n",argv[2]);
    exit(1);
    }
    //对参数进行匹配
    if(!strcmp(argv[1],"-c")){//统计字符数
    number = getChar(fp);
    printf("字符数为%d\n",number);
    } else if(!strcmp(argv[1],"-w")){//统计单词数
    number = getWord(fp);
    printf("单词数为%d\n",number);
    } else if(!strcmp(argv[1],"-l")){//统计行数
    number = getLine(fp);
    printf("行数为%d\n",number);
    } else if(!strcmp(argv[1],"-a")){
    printf("空行行数为%d\n",getnull_line(fp));
    int a,b;
    getcomplex_data(fp,a,b);
    printf("注释行数为%d\n",a);
    printf("代码行数为%d\n",b);
    }
    else if(!strcmp(argv[1],"-s")){
    handle_file();
    }
    }
    else {
    printf("错误:参数输入错误,请重新输入\n");
    } }

六、测试运行

  • 测试文件

    • 空文件: null.txt
    • 只有一个字符的文件: oneChar.txt
    • 只有一个词的文件: oneWord.txt
    • 只有一行的文件: oneLine.txt
    • 一个典型的源文件:file.txt
  • 测试结果









七、总结

  1. 对C语言文件操作的熟练度不够,这个项目基本上是边学习边做的,因此出现了比较多的困难。所以要尽量在做项目之前就把相关知识吃透,这样可以节约很多时间
  2. 因为这次项目是用命令行进行代码运行的,反复打开操作不便。所以最好先把相关模块在编译器上运行成功后,再加入到项目中,这样可以避免反复打开命令行。
  3. 在做项目期间,出现的一个比较大的问题就是,在每次进行文件操作后没有调用rewind()函数,让文件指针调整回开头,这会导致在下一次使用文件时不是从文件开头开始操作的,造成结果的出错。
  4. 项目还欠缺的一点是在统计空行/注释行/代码行时,写的有点复杂,其实这几个函数可以汇总在一起,但自己在敲代码时,结果总会出错,这部分的内容会在之后完善的。

个人项目(WordCount C语言)的更多相关文章

  1. 个人项目WordCount(C++/QT)

    个人项目WordCount(C++/QT) GitHub项目地址:https://github.com/Nova-cjp/Word-Count 百度云链接:https://pan.baidu.com/ ...

  2. 转:从开源项目学习 C 语言基本的编码规则

    从开源项目学习 C 语言基本的编码规则 每个项目都有自己的风格指南:一组有关怎样为那个项目编码约定.一些经理选择基本的编码规则,另一些经理则更偏好非常高级的规则,对许多项目而言则没有特定的编码规则,项 ...

  3. WordCount C语言实现求文本的字符数,单词数,行数

    1.码云地址: https://gitee.com/miaomiaobobo/WordCount 2.psp表格 PSP2.1表格 PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) P ...

  4. 个人项目WordCount基础功能

    码云地址:https://gitee.com/stedylan/WordCount 1.PSP表格: PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) Planning 计划 10 1 ...

  5. Asp.Net Core MVC项目实现多语言(Globalization/Localization)

    正好最近手上在给一个Razor MVC项目实现一个多语言功能,叫Globalization也好,Localization也好,whatever.最终要实现的效果呢,就是一键切换全站语言,并且开发的时候 ...

  6. 结对项目-WordCount

    结对作业: 成员:201631062115(me),201631062613(partner) 代码地址:https://gitee.com/ackary/WordCount 作业的链接地址:http ...

  7. Maven Java项目添加Scala语言支持

    为了在一个普通的使用Maven构建的Java项目中,增加对Scala语言的支持.使得其能够同时编译Java和Scala语言的文件.其实很简单的一件事情,只需要在pom.xml文件中的build部分中的 ...

  8. 个人项目-词频统计(语言:C++)

    词频统计 (个人项目) 要求 (1). 实现一个控制台程序,给定一段英文字符串,统计其中各个英文单词(4字符以上含4字符)的出现频率. 附加要求:读入一段文本文件,统计该文本文件中单词的频率. (2) ...

  9. 个人项目-wordcount

    源代码上传到github的网址为:https://github.com/fancy-dawning/hello-world.git. wc.exe是一个常见的工具,它能统计文本文件的字符数,单词数和行 ...

随机推荐

  1. 修改python默认版本

    查看默认Python版本 python -V 1.安装gcc,用于编译Python源码 yum install gcc 2.下载源码包,https://www.python.org/ftp/pytho ...

  2. stringsream用法

    stringstream: 头文件: #include <sstream> 简单整理一下这玩意的作用,主要有三个吧. 类型转化 字符串拼接 字符串整合(这一个用处特别大!!!!!!!) 先 ...

  3. PHP image2wbmp - 输出WBMP图片

    image2wbmp — 以 WBMP 格式将图像输出到浏览器或文件.高佣联盟 www.cgewang.com 语法 int image2wbmp ( resource $image [, strin ...

  4. PHP image_type_to_extension - 获取图片后缀

    image_type_to_extension — 根据指定的图像类型返回对应的后缀名.高佣联盟 www.cgewang.com 语法 string image_type_to_extension ( ...

  5. Skill 如何翻转一个list

    https://www.cnblogs.com/yeungchie/ code 发现已经有内置了reverse(l_list) unless(fboundp('reverse) procedure(y ...

  6. 51nod 1584 加权约数和 约数和函数小trick 莫比乌斯反演

    LINK:加权约数和 我曾经一度认为莫比乌斯反演都是板子题. 做过这道题我认输了 不是什么东西都是板子. 一个trick 设\(s(x)\)为x的约数和函数. 有 \(s(i\cdot j)=\sum ...

  7. C/C++编程笔记:流行的数字游戏【2048】,C语言400行源代码分享

    游戏介绍 你玩过2048吗?2048是一款流行于各大网页和手机的数字游戏,手机安卓版推出的是<挑战2048>,之后的版本中还加入了双人对战的游戏模式,更加受到玩家的热捧. 2048的游戏规 ...

  8. 动态生成HTML元素-模拟在线考试功能

    前言 我们在项目开发过程中,经常会遇到页面html元素无法提前预设,而是通过某一些条件动态生成的情况,这里我们需要考虑如下几个因素: 1.需要动态创建的元素类型,比如TextBox, Radio, C ...

  9. xml schema杂谈

    有一些场景,我们需要写xml,又需要对内容进行约束,比如智能输入某个值范围,只能写入固定值 这个时候我们就需要xml schema 这个,百度解释为 XML Schema 的作用是定义 XML 文档的 ...

  10. springboot 使用mybatis-generator自动生成代码

    这里只介绍mybatis generator生成代码 一.pom配置 在build-->plugins-->添加plugin <plugin> <groupId>o ...