写在前面

上传的作业代码与测试代码放在GitHub上了 https://github.com/IHHHH/gitforwork

本次作业用的是C语言来完成,因为个人能力与时间关系,只完成了基本功能,扩展功能和高级功能很遗憾没有完成。

基本功能

wc.exe -c file.c               //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的单词总数
wc.exe -l file.c //返回文件 file.c 的总行数
wc.exe -o outputFile.txt //将结果输出到指定文件outputFile.txt

PSP表格

  • 关于预估耗时比实际耗时多的原因,并不是因为能力比预估的高,而是一下几点原因:

    - 预估耗时是以完成除高级功能外所有功能,包括基本功能和扩展功能,而实际任务中,并没有实现扩展功能,仅仅完成了基本功能

    - 完成较少的功能代表着需要较少的时间来学习新的函数和语法

    - 报告因为ddl的原因写得比较匆忙,所用时间较少

    - 预估耗时是六个该项作业的估计时间,实际上有很多其他事情要处理,并没有留下这么多时间,也就是说其他的事情通过尽量压缩来尽量满足预留时间。

设计思路

  1. 实现将数据写入指定文件,读取指定文件的数据并输出
  2. 实现读取指定文件的行数,字符数,单词数并直接输出
  3. 从用户输入的字符串中提取相应的处理字,文件名并直接输出
  4. 将提取到的关键字与之前实现的功能进行对接
  5. 测试程序的一般情况与临界情况

程序分析

char* t;        //result
char* wr; //output
char a[50]; //记录输入数据
char b[50]; //记录读取的文件地址
char WC[1000]; //保存打开的文件内容 int col_count(const char* t); //统计字符数
int col_row(const char* t); //统计行数
int col_word(const char* t); //统计单词数
void result(const char* t, const char* a, int num); //产生结果文件
void output(const char* t, const char* w, int count, int row, int word);//产生输出文件

通过两个指针记录可能出现的两个文件地址字符串的首地址,为了简便,b数组中相应数据的位置与a相同,通过指针进行读取。

for (int i = 0; a[i] != NULL; i++)
{
if(a[i] == '-')
if (a[i+1] == 'o')
for (int j = i+1; a[j] != NULL; j++)
{
if (a[j] == ' ')
if (a[j + 1] != ' '&&a[j + 1] != '-') //输出文件入口判断
{
wr = a + j + 1;
break;
}
}
}

通过对输入信息的判断来提取代表文件地址的字符串

	for (int i = 1; a[i] != NULL; i++)
{
if (a[i - 1] == ' ')
if (a[i] != ' '&&a[i] != '-') //目标文件名入口判断
{
int j = i;
while (a[i] != ' '&&a[i] != NULL) //目标文件名出口判断
{
b[i] = a[i];
i++;
}
t = b + j;
break;
}
}

默认读取的文件在需要写入的文件前,因此读取的文件判断相对复杂,需要对入口和出口同时进行判断

if(a[i] == '-')
{
if (a[i + 1] == 'c')
{
count = col_count(t);
printf_s("字符数:%d", count);
result(t, "字符数", count);
printf_s("\n");
}
if (a[i + 1] == 'l')
{
row = col_row(t);
printf_s("行数:%d", row);
result(t, "行数", row);
printf_s("\n");
}
if (a[i + 1] == 'w')
{
word = col_word(t);
printf_s("单词数:%d", word);
result(t, "单词数", word);
printf_s("\n");
}
if (a[i + 1] == 'o')
{
output(t, wr, count, row, word);
printf_s("\n");
}
}

通过“-”后面的不同情况应用不同的函数

int col_count(const char* t)
{
char data;
FILE *fp;
errno_t err;
int count = 0;
err = fopen_s(&fp, t, "r");
if (err != 0)
{
printf("can't open file\n");
count = -1;
}
while ((data = getc(fp)) != EOF)
{
WC[count] = data;
count++;
}
fclose(fp);
return count;
} int col_row(const char* t)
{
char data;
FILE *fp;
errno_t err;
int row = 0;
err = fopen_s(&fp, t, "r");
if (err != 0)
{
printf("can't open file\n");
row = -1;
}
while ((data = getc(fp)) != EOF)
if (data == '\n')
row++;
fclose(fp);
return row;
} int col_word(const char* t)
{
char data;
FILE *fp;
errno_t err;
int word = 0;
int i = 0;
err = fopen_s(&fp, t, "r");
if (err != 0)
{
printf("can't open file\n");
word = -1;
}
while ((data = getc(fp)) != EOF)
{
WC[i] = data;
i++;
}
if (WC[0] != ' ' && WC[0] != ',' && WC[0] != '\n')
word++;
for (i = 0; WC[i] != NULL; i++)
{
if (WC[i] == ' ' || WC[i] == ',' || WC[i] == '\n')
if (WC[i + 1] != ' ' && WC[i + 1] != ',' && WC[i + 1] != '\n')
word++;
}
fclose(fp);
return word;
}

以上三个函数为需要实现功能函数,均用getc()函数对文件按照一个字符一个字符的方式读取,不同的是自变量的递增条件

判断字符数时,每读取一个就加1,初值为0

判断行数时,每读取一个换行符加1,初值为1

判断单词数时,进行单词的开头与结尾判断,每对应一次加一,但根据判断条件不同,有时要加上开头或者结尾的一个单词

void result(const char* t, const char* a, int num)
{
FILE *wt;
errno_t err;
err = fopen_s(&wt, "result.txt", "a+");
if (err != 0)
{
printf("can't write file\n");
}
fprintf(wt, "%s,%s:%d\n", t, a, num);
fclose(wt);
} void output(const char* t, const char* w, int count, int row, int word)
{
FILE *wt;
errno_t err;
err = fopen_s(&wt, w, "a+");
if (err != 0)
{
printf("can't write file\n");
}
fprintf(wt, "%s,字符数:%d,行数:%d,单词数:%d", t, count, row, word);
fclose(wt);
}

写文件函数,a+表示不擦除之前所写的内容,且去掉之前的停止符EOF

测试

测试思路

测试要覆盖可能出现的左右情况,尽量找到代码中可能蕴含的错误并改正,因此,测试设计应该覆盖判断中的各种边界情况,,满足基本功能的所有需求,-c –w –l -o

用于测试的输入

-c test.txt

-w test.txt

-l test.txt

-c –w test.txt

-c –l test.txt

-w –l test.txt

-c –w –l test.txt

-c test.txt –o output.txt

-w test.txt –o output.txt

-l test.txt –o output.txt

-c –w test.txt –o output.txt

-c –l test.txt –o output.txt

-w –l test.txt –o output.txt

-c –w –l test.txt –o output.txt

没有写测试脚本,但测试均可通过,表示基本功能没有问题

不足

除了扩展功能和高级功能没有完成外,有以下几个不足

  1. 生成的result.txt和outut.txt由于没有在程序内部进行清空,会导致在多次运行后,文件内部信息比较杂乱
  2. 默认先-c-w-l读取文件,再-o保存数据,因此无法在二者翻转时进行正确执行,但由于需求内没有标明,没有考虑该种情况,希望老师验收时注意
  3. 有多个功能聚集在主函数内部,比较杂乱,没有比较好的代码优化。

收获

本次作业除了加强编程能力外,让我们对时间安排有了更充分的理解,理解了上课所学习的基本内容,初步理解的测试的相关方法,希望能在今后的学习中对软件测试有更加深刻的理解和学习

wordcount(C语言)的更多相关文章

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

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

  2. 个人项目(WordCount C语言)

    WordCount程序(C语言) Github地址:https://github.com/peter-ye-code/WordCount 一.题目描述 实现一个简单而完整的软件工具(源程序特征统计程序 ...

  3. 软件工程-wordcount(C语言实现)

    Github项目地址:https://github.com/xiaobaot/wordcount-wc/tree/master WC 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数 ...

  4. WordCount:C语言实现

    项目地址:https://github.com/m8705/WordCount 项目要求 wc.exe 是一个常见的工具,它能统计文本文件的字符数.单词数和行数. 这个项目要求写一个命令行程序,模仿已 ...

  5. 结对编程项目——C语言实现WordCount Web化

    结对编程项目 代码地址 201631062219,201631011410 gitee项目地址:https://gitee.com/xxlznb/pair_programming 作业地址:https ...

  6. Scala,Java,Python 3种语言编写Spark WordCount示例

    首先,我先定义一个文件,hello.txt,里面的内容如下: hello sparkhello hadoophello flinkhello storm Scala方式 scala版本是2.11.8. ...

  7. Spark源码编译并在YARN上运行WordCount实例

    在学习一门新语言时,想必我们都是"Hello World"程序开始,类似地,分布式计算框架的一个典型实例就是WordCount程序,接触过Hadoop的人肯定都知道用MapRedu ...

  8. 软件工程-构建之法 WordCount小程序 统计文件中字符串个数,单词个数,词频,行数

    一.前言 在之前写过一个词频统计的C语言课设,别人说你一个大三的怎么写C语言课程,我只想说我是先学习VB,VB是我编程语言的开始,然后接触到C语言及C++:再后来我是学习C++,然后反过来学习C语言, ...

  9. 利用Scala语言开发Spark应用程序

    Spark内核是由Scala语言开发的,因此使用Scala语言开发Spark应用程序是自然而然的事情.如果你对Scala语言还不太熟悉,可 以阅读网络教程A Scala Tutorial for Ja ...

随机推荐

  1. 坑爹的A标签 href

    A标签 href在与click事件同时响应时,如果click事件有提交表单动作,href会阻拦表单提交,解决 1.去掉href 2.href="javascript:void();" ...

  2. Ubuntu 安装HBase

    下载:http://mirror.bit.edu.cn/apache/hbase/stable/ 官方指南:http://abloz.com/hbase/book.html 安装配置: 解压: tar ...

  3. Odoo 8.0 new API 之one装饰

    one装饰器的作用是对每一条记录都执行对应的方法,相当于traditional-style中的function 应用举例: 定义的columns now = fields.Datetime(compu ...

  4. Unix系统编程()发送信号kill

    与shell的kill命令类似,一个进程能够使用kill系统调用向另一进程发送信号. 之所以选择kill作为术语,因为早期UNIX实现中大多数信号的默认行为是终止进程. #include <si ...

  5. 扩展RBAC用户角色权限设计方案<转>

    RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联.简单地说,一个用户拥有若干角色,每一个角色拥有若干权限.这样,就构造成“用户-角色- ...

  6. HTML5中的拖放

    关于HTML5中的拖放 拖放(Drag 和 Drop)是一种常见的特性,即抓取对象以后拖到另一个位置,在 HTML5 中,拖放是标准的组成部分.在HTML5中用户可以使用鼠标选择一个可拖动元素,将元素 ...

  7. Android——Android Bundle类(转)

    今天发现自己连Bundle类都没有搞清楚,于是花时间研究了一下. 根据google官方的文档(http://developer.android.com/reference/android/os/Bun ...

  8. Math - Uva 11300 Spreading the Wealth

    Spreading the Wealth Problem's Link ---------------------------------------------------------------- ...

  9. 关于Nvelocity的主要语法和一些代码示例

    context.Response.ContentType = "text/html"; VelocityEngine vltEngine = new VelocityEngine( ...

  10. 【BZOJ】1609: [Usaco2008 Feb]Eating Together麻烦的聚餐(dp+被坑)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1609 首先我不得不说,我被这题坑了.题目前边没有说可以不需要3种牛都有啊!!!!!!!!然后我一直在 ...