标签:大小 并且 github null war 好的 语言 任务 当前目录
github地址:https://github.com/7AAAAAAA/c-wc.exe
实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:
wc.exe [parameter] [file_name]
一个功能一个模块,然后根据输入参数不同选择进行不同的功能模块
下面的遇到的困难及解决方法同时也是找资料的心路历程
计算字符数的函数chars
fgetc到一个字符就count++
int chars(char* name){
FILE *fp;
int ch;
int count = 0;
if((fp = fopen(name,"r")) == NULL ){
printf("file: %s\n",name);
printf("错误:找不到该文件或者打不开该文件\n");
count = -1;
}
else {
while((ch = fgetc(fp)) != EOF) {
count++;
}
}
fclose(fp);
if(count >= 0) {
printf("file: %s\n char: %d\n",name,count);
}
return 0;
}
计算词数的函数words
flag:当遇到字母时变成1,然后count++,然后当遇到非字母时就又变成0
int words(char* name){
FILE *fp;
int ch;
int flag = 0;
int count = 0;
if((fp = fopen(name,"r")) == NULL ){
printf("file: %s\n",name);
printf("错误:找不到该文件或者打不开该文件\n");
count = -1;
}
else {
while((ch = fgetc(fp)) != EOF) {
if((ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') && flag == 0){
flag = 1;
}else if(((ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z') && flag == 1) || flag == 0){
continue;
}else if(flag == 1) {
count++;
flag = 0;
}
}
if(flag == 1) {
count++;
}
}
fclose(fp);
if(count >= 0) {
printf("file: %s\n word: %d\n",name,count);
}
return count;
}
计算行数的函数lines
fgetc到一个换行符就为一行
然后有一个flag标志来决定第一行算不算一行,如果没有任何字符,那么就不会count++
int lines(char* name){
FILE *fp;
int ch;
int count = 0;
int flag = 0;
if((fp = fopen(name,"r")) == NULL ){
printf("file: %s\n",name);
printf("错误:找不到该文件或者打不开该文件\n");
count = -1;
}
else {
while((ch = fgetc(fp)) != EOF) {
flag = 1;
if(ch == '\n'){
count++;
}
}
if(flag == 1){
count++;
}
}
fclose(fp);
if(count >= 0) {
printf("file: %s\n line: %d\n",name,count);
}
return count;
}
计算空行数,代码行数和注释行数的函数mores(啊好长的)
利用四个标志
flag:可显示字符为0,1或者超过1
flagcommit:这一行是否已被加为注释行
flagcode:这一行是否已被加为代码行
flagchar:文件中是否有任何字符
来表示这一行的情况
具体想法非常简单,就是考虑多种情况,然后用标志来判断,代码好长
int mores(char* name){
FILE *fp;
int ch;
int count[3] = {0,0,0};
int flag = 0; //超过一个可显示字符才会为1
int flagcommit = 0;//这一行是否已被加为注释
int flagcode = 0;//这一行是否已被加为代码
int flagchar = 0;//文件中是否有任何字符
if((fp = fopen(name,"r")) == NULL ){
printf("file: %s\n",name);
printf("错误:找不到该文件或者打不开该文件\n");
count[0] = -1;
}
else {
while((ch = fgetc(fp)) != EOF) {
if(flagchar == 0) {
flagchar = 1;
}
if(ch == '/') { //遇到一个/
if((ch = fgetc(fp)) != EOF){
if(ch == '/') {
if(flag == 2 && flagcode == 0) {
count[1]++;
flagcode = 1;
}
if(flagcommit == 0 && flagcode == 0){
count[2]++;
flagcommit = 1;
}
while((ch = fgetc(fp)) != EOF) {
if(ch == '\n') {
flag = 0;
flagcode = 0;
flagcommit = 0;
break;
}
}
}else if(ch == '*') {
if(flag == 2 && flagcode == 0) {
if(flagcommit == 1) {
count[2]--;
}
count[1]++;
flagcode = 1;
}
if(flagcommit == 0 && flagcode == 0){
count[2]++;
flagcommit = 1;
}
while((ch = fgetc(fp)) != EOF) {
if(ch == '\n') {
count[2]++;
flagcommit = 0;
flagcode = 0;
flag = 0;
}else if(ch == '*') {
if((ch = fgetc(fp)) != EOF) {
if(ch == '/') {
flagcommit = 1;
break;
}
}
}
}
}
}
}else if(ch >'\x20'){ //不知道后面什么情况,bug待定
if(flag == 0){
flag = 1;
}else if(flag == 1) {
flag = 2;
}
}else if(ch == '\n') {
if((flag == 0 || flag == 1) && flagcode == 0 && flagcommit == 0){
count[0]++;
}else if(flag == 2 && flagcode == 0){
count[1]++;
}
flag = 0;
flagcommit = 0;
flagcode = 0;
}else {
continue;
}
}
}
if((flag == 0 || flag == 1 )&& flagcode == 0 && flagcommit == 0 && flagchar == 1){
count[0]++;
}else if(flag == 2 && flagcode == 0 && flagcommit == 0) {
count[1]++;
}else if(flag == 2 && flagcode == 0 && flagcommit == 1) {
count[1]++;
count[2]--;
}
fclose(fp);
if(count[0] >= 0) {
printf("file: %s\n empty:%d\t code: %d\tnote: %d\n",name,count[0],count[1],count[2]);
}
return 0;
}
除了-s外的其它命令的选择函数somecmdselect
根据参数不同选择不同操作
int somecmdselect(char* cmd,char* file) {
if(strcmp(cmd,"help") == 0) {
printf(" -c file.c 返回文件file.c的字符数\n");
printf(" -w file.c 返回文件file.c的词的数目\n");
printf(" -l file.c 返回文件file.c的行数\n");
printf(" -a file.c 返回文件file.c的空行/代码行/注释行\n");
printf(" -s a b 返回当前目录及子目录中符合b条件的a操作\n");
printf(" a可为-c/-w/-l/-a\n");
printf(" b可为*/*.c等(此处仅支持*.c)");
}else if(!file){
printf("缺少参数\n");
printf("可通过 help参数查看可使用命令\n");
}else if(strcmp(cmd,"-c") == 0) {
chars(file);
}else if(strcmp(cmd,"-w") == 0) {
words(file);
}else if(strcmp(cmd,"-l") == 0) {
lines(file);
}else if(strcmp(cmd,"-a") == 0) {
mores(file);
}else {
printf("\'%s\'命令不存在\n",cmd);
printf("可通过 help参数查看可使用命令\n");
}
return 0;
}
递归处理当前目录以及子目录的.c文件的函数watchfiles(待优化)
利用_findfirst函数和_findnext函数来搜索文件,当搜到文件夹就进入递归,搜到符合条件的文件就进入命令选择函数somecmdselect进行选择,然后执行操作
int watchfiles(char* folder,char* factor,char* argv[]){
struct _finddata_t f;
long handle;
char* currentfactor = (char*)malloc(sizeof(char*)*(strlen(folder)+strlen(factor)+2));//存放当前目录的factor
char* currentfolder= (char*)malloc(sizeof(char*)*(strlen(folder)+strlen(factor)+2));//当前目录
char* path = (char*)malloc(sizeof(char*)*(strlen(folder)+2));
strcpy(path,folder);
strcpy(currentfactor,strcat(path,"/"));
strcpy(currentfolder,path);
handle = _findfirst(strcat(currentfactor,factor),&f);
if(handle == -1L) {
return 0;
}else {
do{
if(f.attrib != _A_SUBDIR){
char* name = (char*)malloc(sizeof(char*)*(strlen(path)+strlen(f.name)));
strcpy(name,path);
somecmdselect(argv[2],strcat(name,f.name));
free(name);
}
}while(_findnext(handle,&f) == 0);
}
free(currentfactor);
_findclose(handle);
handle = _findfirst(strcat(currentfolder,"*"),&f);
if(handle == -1L) {
return 0;
}else {
do{
if(f.attrib == _A_SUBDIR && strcmp(f.name,".") && strcmp(f.name,"..")){
char* newpath = (char*)malloc(sizeof(char*)*(strlen(path)+strlen(f.name)));
strcpy(newpath,path);
watchfiles(strcat(newpath,f.name),factor,argv);
free(newpath);
}
}while(_findnext(handle,&f) == 0);
}
_findclose(handle);
free(currentfolder);
free(path);
return 0;
}
头文件
#include <stdio.h>
#include <string.h>
#include <io.h>
#include <stdlib.h>
主函数
int main(int argc, char* argv[]){
if(argc > 1){
if(strcmp(argv[1],"-s") == 0){
if(argc > 3){
watchfiles(".","*.c",argv);
}else {
printf("缺少参数\n");
printf("可通过 help参数查看可使用命令\n");
}
}else {
somecmdselect(argv[1],argv[2]);
}
}else {
printf("缺少参数\n");
printf("可通过 help参数查看可使用命令\n");
}
return 0;
}
help功能
chars(),words().lines()用的测试文件为
chars()
words()
lines()
mores()用到的测试文件,
扩展功能mores()
扩展功能watchfiles()
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 20 |
· Estimate | · 估计这个任务需要多少时间 | 30 | 20 |
Development | 开发 | 1980 | 2010 |
· Analysis | · 需求分析 (包括学习新技术) | 600 | 400 |
· Design Spec | · 生成设计文档 | 120 | 100 |
· Design Review | · 设计复审 (和同事审核设计文档) | 60 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 60 | 30 |
· Design | · 具体设计 | 180 | 160 |
· Coding | · 具体编码 | 480 | 720 |
· Code Review | · 代码复审 | 120 | 100 |
· Test | · 测试(自我测试,修改代码,提交修改) | 360 | 480 |
Reporting | 报告 | 600 | 270 |
· Test Report | · 测试报告 | 240 | 180 |
· Size Measurement | · 计算工作量 | 120 | 30 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 240 | 60 |
合计 | 2610 | 2300 |
标签:大小 并且 github null war 好的 语言 任务 当前目录
原文地址:https://www.cnblogs.com/7AAAAAAA/p/12445639.html