个人项目(WordCount C语言)
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 |
三、思路
- 刚开始拿到题目,就决定用C语言去做这个项目,因为自己学习的高级语言只有C和JavaScript,对于C语言的话更有把握一些。
- 在开始着手做这个项目时,我先通过网上资源得知这个项目的关键知识点是对文件的操作,如fgetc和fgets函数,于是就花了一些时间在文件操作的学习上。
- 在学习完相关文件操作后,就开始进行相关模块的开发,之后再汇总成一个大模块
四、设计实现过程
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
测试结果
七、总结
- 对C语言文件操作的熟练度不够,这个项目基本上是边学习边做的,因此出现了比较多的困难。所以要尽量在做项目之前就把相关知识吃透,这样可以节约很多时间
- 因为这次项目是用命令行进行代码运行的,反复打开操作不便。所以最好先把相关模块在编译器上运行成功后,再加入到项目中,这样可以避免反复打开命令行。
- 在做项目期间,出现的一个比较大的问题就是,在每次进行文件操作后没有调用
rewind()
函数,让文件指针调整回开头,这会导致在下一次使用文件时不是从文件开头开始操作的,造成结果的出错。 - 项目还欠缺的一点是在统计空行/注释行/代码行时,写的有点复杂,其实这几个函数可以汇总在一起,但自己在敲代码时,结果总会出错,这部分的内容会在之后完善的。
个人项目(WordCount C语言)的更多相关文章
- 个人项目WordCount(C++/QT)
个人项目WordCount(C++/QT) GitHub项目地址:https://github.com/Nova-cjp/Word-Count 百度云链接:https://pan.baidu.com/ ...
- 转:从开源项目学习 C 语言基本的编码规则
从开源项目学习 C 语言基本的编码规则 每个项目都有自己的风格指南:一组有关怎样为那个项目编码约定.一些经理选择基本的编码规则,另一些经理则更偏好非常高级的规则,对许多项目而言则没有特定的编码规则,项 ...
- WordCount C语言实现求文本的字符数,单词数,行数
1.码云地址: https://gitee.com/miaomiaobobo/WordCount 2.psp表格 PSP2.1表格 PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) P ...
- 个人项目WordCount基础功能
码云地址:https://gitee.com/stedylan/WordCount 1.PSP表格: PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) Planning 计划 10 1 ...
- Asp.Net Core MVC项目实现多语言(Globalization/Localization)
正好最近手上在给一个Razor MVC项目实现一个多语言功能,叫Globalization也好,Localization也好,whatever.最终要实现的效果呢,就是一键切换全站语言,并且开发的时候 ...
- 结对项目-WordCount
结对作业: 成员:201631062115(me),201631062613(partner) 代码地址:https://gitee.com/ackary/WordCount 作业的链接地址:http ...
- Maven Java项目添加Scala语言支持
为了在一个普通的使用Maven构建的Java项目中,增加对Scala语言的支持.使得其能够同时编译Java和Scala语言的文件.其实很简单的一件事情,只需要在pom.xml文件中的build部分中的 ...
- 个人项目-词频统计(语言:C++)
词频统计 (个人项目) 要求 (1). 实现一个控制台程序,给定一段英文字符串,统计其中各个英文单词(4字符以上含4字符)的出现频率. 附加要求:读入一段文本文件,统计该文本文件中单词的频率. (2) ...
- 个人项目-wordcount
源代码上传到github的网址为:https://github.com/fancy-dawning/hello-world.git. wc.exe是一个常见的工具,它能统计文本文件的字符数,单词数和行 ...
随机推荐
- 什么是 PHP 过滤器?
PHP 过滤器 PHP 过滤器用于验证和过滤来自非安全来源的数据,比如用户的输入. 什么是 PHP 过滤器? PHP 过滤器用于验证和过滤来自非安全来源的数据. 测试.验证和过滤用户输入或自定义数据是 ...
- PHP stripcslashes() 函数
实例 删除 "World!" 前面的反斜杠: <?php高佣联盟 www.cgewang.comecho stripslashes("Hello World!&qu ...
- Skill Virtuoso IC6.1.7 的所有View Type
https://www.cnblogs.com/yeungchie/ 可以用deGetAllViewTypes()来获取. "graphic" "layout" ...
- 剑指 Offer 58 - I. 翻转单词顺序
本题 题目链接 题目描述 我的题解 方法一:库函数split() 要注意str.split()函数: 字符串str前有 n 个空格时,分割出来的字符串列表中会多出 n 个空字符串: 字符串str某两个 ...
- ABP使用Nginx代理导致租户ID(Abp.TenantId)丢失
描述:ABP使用Nginx代理导致租户ID(Abp.TenantId)丢失,自定义header无效无法传递,导致租户选择认证失败.原因是因为 Nginx 过滤是“.”这符号. 解决: 1,先从代码人手 ...
- SpringCloud服务注册中心
SpringCloud服务注册中心 Spring Cloud 是一系列框架的有序集合,如服务注册发现.配置中心.消息总线.负载均衡.断路器等,都可以用 Spring Boot 的开发风格做到一键启动和 ...
- 基于asp.net core 从零搭建自己的业务框架(一)
前言 asp.net core版本选择2.2,只是因为个人习惯了vs2017,代码以及设计皆可移植到vs2019,用asp.net core 3.0以及以上运行起来 项目类似选择web api,基础设 ...
- Kaggle-pandas(2)
Intndexing-selecting-assigning 教程 介绍选择要处理的pandas DataFrame或Series的特定值是几乎将要运行的任何数据操作中的一个隐含步骤,因此在Pytho ...
- 史上最全的微信小程序代码大全
--------------------- 本文来自 fenxiangjun 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/fenxiangjun/article/d ...
- Docker 快速搭建 MySQL 5.6 开发环境
使用 Docker 快速搭建一个 MySQL 5.6 开发环境 步骤 获取镜像 docker pull mysql:5.6 启动容器,密码 123456,映射 3306 端口 docker run - ...