github地址

https://github.com/lzwk/WordCount

PSP表格

PSP2.1

PSP阶段

预估耗时(分钟)

实际耗时(分钟)

Planning

计划

20

40

· Estimate

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

20

30

Development

开发

600

900

· Analysis

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

100

150

· Design Spec

· 生成设计文档

20

30

· Design Review

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

60

70

· Coding Standard

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

10

20

· Design

· 具体设计

50

55

· Coding

· 具体编码

500

600

· Code Review

· 代码复审

150

200

· Test

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

200

200

Reporting

报告

100

120

· Test Report

· 测试报告

40

50

· Size Measurement

· 计算工作量

20

30

· Postmortem & Process Improvement Plan

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

20

30

 

合计

1910

2525

解题思路

利用控制台执行exe文件,同时传入main()函数的形参,根据传入的形参的不同执行相应的功能,如:字符数、单词数、行数等,不同的输入搭配可以实现不同的高级功能。

程序设计实现过程

本项目采用C语言实现,除main函数外,还有多个自定义函数,其中两个最主要的函数为count()和none(),count()用来统计单词数、行数、注释行数,none()用来统计空行数。

main()函数根据传入的形参的不同,完成不同的输出。其余自定义行数比较简单,下面代码说明中会以isNewline()函数为例进行解释。

代码说明

count()函数用以统计单词数、行数、注释行数,函数中有单词判断,没检测出一个单词word_num+1;每遇到一个'\n',line_num+1;没有到注释行,note_num+1,如果是/*note*/注释,在主是内部没出现一次‘\n’,note_num+1。

int count()//统计单词数、行数、注释行数
{
get();
clearToken();
while (isSpace(ch) || isNewline(ch) || isTab(ch) || isComma(ch))
{
if (isNewline(ch)) line_num++;
get();
}
if (isStar(ch))
{
catToken(ch);
}
else if (isDivi(ch))
{
catToken(ch);
get();
if (isStar(ch))
{
note_num++;
catToken(ch);
do
{
do
{
get();
if (isNewline(ch))
{
note_num++;
line_num++;
} } while (!isStar(ch));
do
{
get();
if (isNewline(ch))
{
note_num++;
line_num++;
}
if (isDivi(ch))
{
catToken(ch);
return ;
}
} while (isStar(ch));
} while (!isStar(ch));
}
if (isDivi(ch))
{
catToken(ch);
do
{
get();
} while (!isNewline(ch));
note_num++;
}
if (isNewline(ch))
line_num++;
}
else if (isEnd(ch))
return ;
else
{
while (!(isSpace(ch) || isNewline(ch) || isTab(ch) || isComma(ch) || isDivi(ch)))
{
catToken(ch);
get();
}
retract();
if(strcmp(stopWord, "") == || strcmp(token,stopWord)!=)
word_num++;
}
return ;
}

以isNewline()为例,解释简单自定义函数:

bool isNewline(char a)
{
if (a == '\n')
return true;
return false;
}

none()函数,根据两个‘\n’中是否小于或等于一个字符来判断是否为空行,满足条件则none_num+1:

void none()//统计空行数
{
int i,j = ;
for (i = ;; i++)
{
if (art[i] == EOF)
break;
if (art[i] != '\n'&& art[i] != '\t'&& art[i] != ' ')
{
j++;
}
if (art[i] == '\n')
{
if (j <= )
none_num++;
j = ;
}
}
}

main()函数,由于功能是逐步添加的,加上自己的代码习惯有待提高,导致main()函数被修改的过于冗杂。重要思想:利用数组flag[7],每一个元素对应一个功能(包括字符数、单词数输出等),为1时表示对应功能执行,反之不执行。

int main(char argc, char* argv[])
{ if (argc<)
printf("请在控制台输入正确命令!\n");
else
{
if (strcmp(argv[], "wc.exe") != )
printf("可执行文件名输入错误!\n");
else
{
for (int i = ; i<argc; i++)
{
if (strcmp(argv[i], "-c") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-w") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-l") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-o") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-s") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-a") == )
{
flag[] = ;
}
else if (strcmp(argv[i], "-e") == )
{
flag[] = ;
}
}
}
} if (flag[] == )
{
_finddata_t sFind;
long lResult = ;
lResult = _findfirst("*.c", &sFind);
if (lResult == -) {
printf("没有找到文件。");
return ;
} int i=,len;
do {
len = strlen(sFind.name);
strcpy_s(filesName[i], len + , sFind.name);//将所有读到的保存到filesname
file_num++;
i++;
} while (_findnext(lResult, &sFind) != -); for (int j = ; j < file_num; j++)
{
fopen_s(&fp, filesName[j], "r");
if (fp == NULL)
printf("error!\n");
int i = ;
do//获取文件内容
{
ch = fgetc(fp);
art[i++] = ch;
} while (ch != EOF);
fclose(fp);
char_num = i; if (flag[] == )//获取停用词
{
fopen_s(&fp, "stopList.txt", "a");
fgets(stopWord, , fp);
fclose(fp);
}
do//核心统计
{
count();
} while (!isEnd(ch));
none(); if (flag[] == )
printf("%s,字符数: %d \n", filesName[j], char_num);
if (flag[] == )
printf("%s,单词数: %d \n", filesName[j], word_num);
if (flag[] == )
printf("%s,总行数: %d \n", filesName[j], line_num);
if (flag[] == )
{
fopen_s(&fp, argv[argc - ], "a");
if (flag[] == )
fprintf(fp, "%s,字符数: %d \n", filesName[j], char_num);
if (flag[] == )
fprintf(fp,"%s,单词数: %d \n", filesName[j], word_num);
if (flag[] == )
fprintf(fp,"%s,总行数: %d \n", filesName[j], line_num);
if (flag[] == )
fprintf(fp, "%s,代码行/空行/注释行: %d/%d/%d \n", filesName[j], line_num - note_num - none_num, none_num, note_num);
fclose(fp);
}
if (flag[] == )
printf("%s,代码行/空行/注释行: %d/%d/%d \n", filesName[j], line_num - note_num - none_num, none_num, note_num);
strcpy_s(stopWord,,"");
for (int i = ; i < ; i++)
art[i] = '\0';
sta = art;
char_num = ;
word_num = ;
line_num = ;
note_num = ;
none_num = ;
}
} else
{
fopen_s(&fp, "file.c", "r");
if (fp == NULL)
printf("error!\n");
int i = ;
do
{
ch = fgetc(fp);
art[i++] = ch;
} while (ch != EOF);
fclose(fp);
char_num = i; if (flag[] == )
{
fopen_s(&fp, "stopList.txt", "r");
fgets(stopWord, , fp);
fclose(fp);
}
do
{
count();
} while (!isEnd(ch));
none(); if (flag[] == )
printf("file.c,字符数: %d \n", char_num);
if (flag[] == )
printf("file.c,单词数: %d \n", word_num);
if (flag[] == )
printf("file.c,总行数: %d \n", line_num);
if (flag[] == )
{
fopen_s(&fp, argv[argc - ], "w");
if (flag[] == )
fprintf(fp, "file.c,字符数: %d \n", char_num);
if (flag[] == )
fprintf(fp, "file.c,单词数: %d \n", word_num);
if (flag[] == )
fprintf(fp, "file.c,总行数: %d \n", line_num);
if (flag[] == )
fprintf(fp, "file.c,代码行/空行/注释行: %d/%d/%d \n", line_num - note_num - none_num, none_num, note_num);
fclose(fp);
}
if (flag[] == )
printf("file.c,代码行/空行/注释行: %d/%d/%d \n", line_num - note_num - none_num, none_num, note_num);
}
printf("\n");
system("pause");
return ;
}

测试设计过程

利用“wc.bat”脚本程序,批量处理,测试用例如下:

测试结果如下:

测试用例中,利用“-o”功能将输出写入文件,其中与“-s”功能同时实现时,写入文件是不会首先清空文件;不与“-s”功能同时实现时,写入文件时会首先清空文件。

可编辑wc.bat来改变测试输入。

参考文献

1.https://www.cnblogs.com/saolv/p/7793379.html

2.https://www.cnblogs.com/chengxs/p/5309215.html

最新文章

  1. lucene 基础知识点
  2. jS字符串大小写转换实现方式
  3. python---time和datetime
  4. 记、基于react-router的单页应用
  5. JQuery Checkbox的change事件
  6. 用mysql时遇到的一些问题
  7. 梯度下降法VS随机梯度下降法 (Python的实现)
  8. yield curve
  9. python 之路,Day11(上) - python mysql and ORM
  10. 关于Winform中的用户代理
  11. ORACLE 监听
  12. 《为大量出现的KPI流快速部署异常检测模型》 笔记
  13. Java开发学习心得(三):项目结构
  14. 《Effective C++》实现:条款26-条款31
  15. Linux Shell函数定义与调用
  16. c语言小项目---通讯录2.0
  17. linux 中的 open() read() write() close() 函数
  18. 【leetcode】283. Move Zeroes
  19. WINDOWS 命令行 串口 COM 发送数据
  20. [UE4]子控件Child Widget顶层容器选择

热门文章

  1. RedHat 6.8 内核编译
  2. myeclipse2014中如何安装freeMarker插件(支持ftl语法高亮)
  3. web.xml &amp; web-fragment.xml (Servlet 2.3, 2.4, 2.5 + 3.0)模板
  4. 作业派NABCD的特点分析
  5. BZOJ4355: Play with sequence
  6. LeetCode Can Place Flowers
  7. GXT4.0 BorderLayoutContainer布局
  8. 【转】Inter-eNB S1 切换
  9. 机器学习:逻辑回归(OvR 与 OvO)
  10. Python多进程-进程锁