github地址:https://github.com/nilonger/mycangku

一、项目要求

1、wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。

2、实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
程序处理用户需求的模式为:wc.exe [parameter] [file_name]

3、基本功能:

wc.exe -c file.c    //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的词的数目
wc.exe -l file.c //返回文件 file.c 的行数

4、扩展功能:

-s   递归处理目录下符合条件的文件。
-a 返回更复杂的数据(代码行 / 空行 / 注释行)。

空行:本行全部是空格或格式控制字符,如果包括代码,则只有不超过一个可显示的字符,例如“{”。
代码行:本行包括多于一个字符的代码。
注释行:本行不是代码行,并且本行包括注释。一个有趣的例子是有些程序员会在单字符后面加注释:
} //注释
在这种情况下,这一行属于注释行。
特殊情况,如 return; } //注释,既算是代码行也算是注释行。
[file_name]: 文件或目录名,可以处理一般通配符

5、高级功能:

-x 参数。这个参数单独使用。如果命令行有这个参数,则程序会显示图形界面,用户可以通过界面选取单个文件,程序就会显示文件的字符数、行数等全部统计信息。

二、PSP

PSP2.1

Personal Software Process Stages

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

50

80

· Estimate

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

500

600

Development

开发

500

600

· Analysis

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

100

200

· Design Spec

· 生成设计文档

20

25

· Design Review

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

20

20

· Coding Standard

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

20

20

· Design

· 具体设计

80

100

· Coding

· 具体编码

150

350

· Code Review

· 代码复审

30

60

· Test

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

30

60

Reporting

报告

20

30

· Test Report

· 测试报告

20

30

· Size Measurement

· 计算工作量

10

10

· Postmortem & Process Improvement Plan

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

10

20

合计

1560

2205

三、解题思路

1、刚开始拿到题目的时候,一脸懵逼,不知道从哪里开始着手,只知道要统计字符数,单词数,总行数。不知道怎么下手,就百度了一下wc,看到了一些用java,Python,C什么的例子,发现其实还而已,然后就开始着手计划打码

2、字符数:只要是在  ‘!’和‘~’  之间的字符,都算入统计范围内

  词数:要求在由英文字母组成  ‘A’~‘Z’  和  ‘a’~‘z’,然后设置一个变量 flag,帮助判断行数是否要 +1

  行数:行数最简单,只要判断换行符 ‘\n’ 就好了

  返回更复杂数据 A :空行,注释行(包括多行注释),代码行,这个几个数据的统计没得参考,只能通过上面那几个数据的统计过程自己           写相应的算法

  递归目录:没有。觉得C语言实现有点难,别的语言又不会。所以放弃。

四、设计实现过程

第一种(也是现在代码的运行顺序):

第二种(之前为了调试单独一个函数的功能):

五、代码说明

统计字符数函数CountC():

#include <stdio.h>
#include<stdlib.h>
#include <string.h> int x,y,z,k,konghang;//x字符数 ; y词数 ;z行数 ; k 注释行数 int m; //不是空文件时 m=1 //字符数
void CountC(char fname[]){
FILE* fp=NULL;
if((fp=fopen(fname,"r"))==NULL) //不要 放在主函数里面
{
printf("打不开文件\n");
exit();
} char ch;
ch=fgetc(fp);
while(ch!=EOF)
{
if(ch>='!'&&ch<='~') //ASCII 从33到126
x++;
ch=fgetc(fp); }
if(x==)m=; //m=0 则为 空文件
fclose(fp);
}

统计单词数函数CountW():

//词数
void CountW(char fname[]){
FILE* fp=NULL;
if((fp=fopen(fname,"r"))==NULL)
{
printf("打不开文件\n");
exit();
} char ch;
int flag=; //用于判断是否要 +1 ,flag要先置为0
ch=fgetc(fp);
while(ch!=EOF)
{
if(!(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')){ //如果是非字母字符,让flag为0 ||ch=='.'||ch=='_'
flag = ;
}
else if((flag ==)&&(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')) //如果是字母字符且flag原值为0,flag置1,单词数加一
{
flag = ;
y++;
}
ch=fgetc(fp);
}
// y--; //单独测试 的时候要加上 ,不知道为什么要 -1
if(m==) y=;
fclose(fp);
}

统计行数CountL():

//行数
int CountL(char fname[]){
FILE* fp=NULL;
if((fp=fopen(fname,"r"))==NULL)
{
printf("打不开文件\n");
exit();
} char ch;
ch=fgetc(fp);
z++; // 单独测试 的时候要去掉
while(ch!=EOF)
{
if(ch=='\n')
z++;
ch=fgetc(fp);
}
if(m==) z=; //不能z-- 空文件运行会出错
fclose(fp);
return(z);
}

统计复杂类型数据函数CountA():

这里没有分开三个函数,而是合在一起。

缺点:见后面总结。

void CountA(char fname[]){
FILE* fp=NULL;
if((fp=fopen(fname,"r"))==NULL)
{
printf("打不开文件\n");
exit();
} //注释行
char ch;
ch=fgetc(fp);
while(ch!=EOF)
{
if(ch=='/')
{
ch=fgetc(fp);
if(ch=='/')
{
k++; //注释行 +1
ch=fgetc(fp); //获得新的字符,并重新开始循环
continue;
}
else if(ch=='*')
{
ch=fgetc(fp); while(ch!=EOF)
{
if(ch=='\n') k++; //多行注释的 每个回车都要 +1
if(ch=='*')
ch=fgetc(fp);
if(ch=='/')
{
k++; //多行注释完整,行数+1,并跳出第二层循环
break;
}
ch=fgetc(fp); } } }
ch=fgetc(fp);
}
printf("注释行:%d\n",k);
rewind(fp); //指回文件开头 //空行
int flag=;
int num=; //两个换行符之间的字符数
konghang=; ch=fgetc(fp);
while(ch!=EOF){
if(ch=='\n'&&num==) //第一个换行符
{
flag=;
konghang++;
} else if(ch!='\n'&&flag==)
num++; else if(ch!='\n'&&flag==&&num==) //第一行 是代码行 的情况
{
num++;
flag=;
}
else if(ch=='\n'&&flag==&&num>=){ //代码行到最后,把累加的字符数 归0
num=;
flag=;
} ch=fgetc(fp);
}
printf("空行数:%d\n",konghang);
rewind(fp); //代码行
int num1=,daimahang=,flag1=;;
ch=fgetc(fp);
while(ch!=EOF){ if((ch!=' '&&ch!='\n'&&ch!='\t'&&ch!='/'))
{
num1++;
}
else if(ch=='\n'&&num1>=&&flag1==)
{
daimahang++;
num1=;
}
else if(ch=='/')
{
ch=fgetc(fp);
if(ch=='/')
{
ch=fgetc(fp);
while(ch!=EOF){
if(ch=='\n') break;
ch=fgetc(fp);
}
}
else if(ch=='*')
{
ch=fgetc(fp);
while(ch!=EOF){
if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')num1++;
if(ch=='\n')num1=;
if(ch=='*')
{
ch=fgetc(fp);
if(ch=='/') break;
}
ch=fgetc(fp);
}
}
} ch=fgetc(fp);
}
daimahang++; //最后一行没有'\n',自动 +1
if(m==) daimahang=;
printf("代码行数:%d\n",daimahang);
fclose(fp); }

主函数:

注释里面的就是 原本用来单独调试单个函数用的第二个流程。(选择 流程1 或  流程2 在运行过程中,同一个文件各数据统计的结果会有所出入,解决方法已经在各个函数里面备注了。)

int main(){

  char fu[];
char fname[];
while(){
m=; //不是空文件是 m=1 x=y=z=k=konghang=;
printf("输入文件名:");
scanf("%s",fname); CountC(fname) ;
printf("字符数为:%d\n",x); CountW(fname);
printf("单词数为:%d\n",y); CountL(fname);
printf("行数:%d\n",z); CountA(fname); } /* printf("-c:统计字符数\n -w:统计单词数\n -l:统计行数\n -a复杂数据\n -9:退出\n"); while(1)
{ x=0;y=1;z=1;k=0; //行数先设置为 1
printf("请输入你的操作c/w/l/a/9:");
scanf("%s",fu); if(fu[0]=='c')
{
CountC(fname) ;
printf("字符数为:%d\n",x);
} if(fu[0]=='w')
{
CountW(fname);
printf("单词数为:%d\n",y);
} if(fu[0]=='l')
{
CountL(fname);
printf("行数:%d\n",z);
} if(fu[0]=='a')
{
CountA(fname);
} if(fu[0]=='9')
break;
}
*/ return ; }

六、测试运行

1、空文件

2、一个字符的文件

3、只有一个词的文件

4、只有一行的文件

5、一个典型的源文件

6、自己乱打的文件:

七、项目小结

1、这次任务从无到有的,从不知如何开始到自己写算法统计复杂数据,过程虽然很无聊,改不好也容易烦躁,但是最后还是基本改完了,很是高兴

2、设置几个固定的文件来做 回归测试 还是远远不够的,这样你代码只会偏向于说:只要满足那几个文件就好了,但是要是文件一改动,代码运行结果马上出现统计问题。所以我在测试的时候,偏向于改变文件里的内容来做测试,改动的次数多了,就可以发现还有那些问题所在,上面的第6个图就是自己乱打的代码,其中通过这个方法就发现并解决的多行注释里可以包含空行的现象,因为注释行可以包含空行,所以  : 代码行!=总行 - 注释行 -空行,因为这样子会多减去一部分,导致代码行比实际少!

3、缺点:1)统计复杂数据的时候,最后一行不能是空行,空行统计会出错

        2)统计复杂数据的时候,最后一行如果有注释,比如(printf();//我是注释,或者最后一行是  ' */ ' ),注释行将不能最后一行统计在内,也就是那一行仍然是属于代码行

        3)我的算法是:只要有注释,该行就归为  注释行

        4)也就发现最后一行这个问题,其他地方没有发现什么问题

  优点:各种数据随便互相嵌套,统计结果基本都不会出现问题(除了上面说的),还有就是,实现了注释行里的可以空行可以计算进去和多行注释里面的代码不包含进代码行等等。

4、局限于现在只会c语言,其他语言比如java,学过一点,但是由于不熟练,就放弃了用java来写,还有就是递归目录没有实现。

5、这个项目所花的时间有点长(还好早一点写),大部分时间用在了分析复杂数据的算法,还有写完算法、优化算法的过程上。

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

  1. 个人项目-wc

    个人项目-WC   (C语言) 一.Github地址:https://github.com/Lin-J-F/WC 二.PSP表格 PSP2.1 Personal Software Process St ...

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

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

  3. 实践简单的项目WC

    #include<iostream> #include<fstream> #include<string> #include<Windows.h> us ...

  4. 个人项目-WC(C/C++ 兼容Linux和Windows)

    一.Github地址 https://github.com/S-TRAVELER/WC 实现的功能: 支持 -c 支持 -w 支持 -l 支持 -s 支持 -a 图形界面 多参数(文件名或通配符表达式 ...

  5. 个人项目-WC (java实现)

    一.Github地址:https://github.com/734635746/WC 二.PSP表格 PSP2.1 Personal Software Process Stages 预估耗时(分钟) ...

  6. 个人项目-WC(Java实现)

    一.Github项目地址: https://github.com/kestrelcjx/-WC-Java- 二.PSP表格 PSP2.1 Personal Software Process Stage ...

  7. 个人项目—WC

     一,Github地址:https://github.com/mushan520/WC.git 二.PSP表格: PSP2.1 Personal Software Process Stages 预估耗 ...

  8. 个人项目 wc.exe

    GitHub地址:https://github.com/oAiuo/wordCount 一.题目描述 Word Count1. 实现一个简单而完整的软件工具(源程序特征统计程序).2. 进行单元测试. ...

  9. 个人项目WC.exe Node.js+electron实现

    前言 实现语言:Javascript 编译工具:webstorm GitHub:https://github.com/NPjuan/WC.git 项目要求 wc.exe 是一个常见的工具,它能统计文本 ...

随机推荐

  1. AttributeError: module 'time' has no attribute 'clock'

    在python3.8中flask项目运行报错: AttributeError: module 'time' has no attribute 'clock'解决方案 主要原因是因为python3.8中 ...

  2. Tkinter常用简单操作

        截图来自北京尚学堂 手册:http://effbot.org/tkinterbook/ 2020-04-20

  3. Pintech品致-高压放大器

      pintech品致推出的HA-520(200KHz,500Vp-p)高压放大器真的是实用的高电压信号放大器, 体积小,轻便及简易的操作, 高电压输出(800Vp-p)等优点.连续输出电流量最大值达 ...

  4. Vuex详细教程

    1.认识Vuex 1.1Vuex是做什么的 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的 ...

  5. 怎么下载腾讯课堂M3U8格式的视频

    好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 前言 用过腾讯课堂的小伙伴们可能 ...

  6. CentOS部署RabbitMQ

    CentOS版本:CentOS-7-x86_64-DVD-1804 RabbitMQ版本:3.7.24 1. 下载安装包 因为RabbitMQ是erlang语言开发的,所以需要提前安装erlang环境 ...

  7. 【小白学AI】八种应对样本不均衡的策略

    文章来自:微信公众号[机器学习炼丹术] 目录 1 什么是非均衡 2 8种解决办法 2.1 重采样(四种方法) 2.2 调整损失函数 2.3 异常值检测框架 2.4 二分类变成多分类 2.5 EasyE ...

  8. Python笔试——毕业旅行问题

    毕业旅行问题 小明目前在做一份毕业旅行的规划.打算从北京出发,分别去若干个城市,然后再回到北京,每个城市之间均乘坐高铁,且每个城市只去一次.由于经费有限,希望能够通过合理的路线安排尽可能的省一些路上的 ...

  9. Linux根目录下文件夹用途解释

    root目录:主要用于存放root用户相关文件的目录: usr目录:安装一个软件时,linux指定的此软件默认安装的目录: home目录:用于存放普通用户的相关文件的目录:例如:我使用adduser ...

  10. Shiro+SpringBoot认证

    该博客以Web为基础 一.引入依赖 shiro-all包含shiro所有的包.shiro-core是核心包.shiro-web是与web整合.shiro-spring是与spring整合.shiro- ...