博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
垃圾“程序是怎样练成的”——关于《C程序设计伴侣》第A章(五)
阅读量:6367 次
发布时间:2019-06-23

本文共 4166 字,大约阅读时间需要 13 分钟。

前文链接:

【样本】

 

// 表示文件的结构体typedef struct _txtfile{    char name[128];         // 文件名    char text[1024*128];    // 文件的文本内容    word* list;                // 保存单词的链表    int total;                 // 单词总数    float correlation;        // 关键词在文件中的词频} txtfile;

 

    ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p283

【评析】

  “将词频添加到txtfile结构体中”是个愚蠢的想法,因为后面要根据词频进行排序,而txtfile中text成员是个极其庞大、笨重的char [1024*128]类型的数据对象。这就跟让一群人抱着水缸但却让他们按的个头高低排好队一样。

【样本】

 

    ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p283

【评析】

  数据结构反反复复一点谱都没有,居然不以为耻反以为荣。

  看到“对于txtfile结构体的不断扩展,也反映了C语言面向结构程序设计中的‘逐步求精’的过程”这句话,任何懂得编程的人恐怕都会产生一种扔臭鸡蛋的冲动。但是这本书的阅读对象是并不懂得编程小朋友。悲夫?!

【样本】

// 计算词频模块的实现// 参数files和count是保存txtfile结构体的数组指针和元素个数,// keyword是要计算词频的关键词void countkeyword(txtfile* files,int count,char* keyword){    // 利用for循环,计算关键词在每一个文件中的词频    for(int i = 0; i < count;++i)    {        // 在当前文件中查找关键词结点        word* keynode = findnode(files[i].list,keyword);        // 如果找到结点,则计算词频        if(NULL != keynode)        {            // 利用单词的个数除以文件的单词总数计算词频            files[i].correlation = keynode->count/(float)files[i].total;        }        else // 如果没有找到,词频为0        {            files[i].correlation = 0.0f;        }    }}

 

   ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p284

【评析】

  本想这回可以不用说什么了。可一不小心看到了第二行注释中的“参数files和count是保存txtfile结构体的数组指针和元素个数”。“数组指针”不知所云。

【样本】

 

#include 
#include
#include
#include
//...int main(){ // 文件读取以及数据预处理… // 无限循环,提供用户查询交互 while(true) { puts("please input the keyword:"); char keyword[30] = ""; // 获取用户输入的关键词 scanf("%s",keyword); // 如果用户输入的是“#”,则表示查询结束退出循环 if(0 == strcmp(keyword,"#")) break; // 计算用户输入的关键词在各个文件中的词频 countkeyword(files,filecount,keyword); } return 0;}

 

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p284~285

【评析】

  “我们还需要在主函数中构造一个无限循环,让用户输入关键词”是奇葩。因为最初问题的要求是“现在要求输入一个关键词”。

  自底向上地写代码最终往往得到的就是这么个效果:本来说是要画美人的,结果画成了张飞。
  代码中

    char keyword[30]="";

 

中的初始化多余,30是MagicNumber。

    scanf("%s",keyword);

 

中存在危险的漏洞。这句话应该写为

scanf("30%s",keyword);

    文雅一点的写法是

#define MAX_LEN 30#define S_(X) #X#define S(X) S_(X)scanf(S(MAX_LEN )"%s",keyword);

 

     if(0 == strcmp(keyword,"#"))       break;

 

也是随心所欲的胡写,因为在最初的要求中根本就没这一条。

    countkeyword(files,filecount,keyword);

这里的filecount和files没有关系,非常滑稽。

  这条语句应该写为

countkeyword(files,sizeof files/sizeof *files,keyword);

 

【样本】

 

#include 
// …// 比较规则函数int cmp(const void* a,const void* b){ // 将void*类型的参数转换为实际的txtfile*类型 const txtfile* file1 = (txtfile*)a; const txtfile* file2 = (txtfile*)b; // 比较txtfile结构体的词频 if(fabs(file1->correlation - file2->correlation) < 0.001) { return 0; } else if(file1->correlation > file2->correlation) { return 1; } else { return -1; }}// 文件排序模块的实现void sortfiles(txtfile* files,int count){ // 调用qsort()函数对数组进行排序 qsort(files,count,sizeof(txtfile),cmp); }// 数据输出模块的实现// 参数files和count是保存txtfile结构体数据的数组,// keyword是本次查询的关键词void printfiles(txtfile* files,int count,char* keyword){ // 输出本次查询的关键词 printf("the keyword is \"%s\"\n",keyword); // 输出这个关键词在各个文件的词频 puts("the correlations are "); for(int i = 0; i < count;++i) { printf("%s %.4f\n",files[i].name,files[i].correlation); }}

 

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p284

【评析】

  “根据问题的要求,我们需要根据各个文件的词频大小,对保存在数组中的txtfile文件结构体进行排序”这个想法很愚蠢,因为问题的要求并非如此,而且只需要根据词频对文件名排序就可以了,然而txtfile(不知道啥叫“txtfile文件结构体”)其他部分一同参与排序简直是吃饱了撑的。

  代码部分:

   cmp()函数形参名称很垃圾。

if(fabs(file1->correlation - file2->correlation) < 0.001)

 

  这样的写法是食古不化,不仅毫无必要,而且弄出了一个MagicNumber 0.001。这里其实可以直接写

if( file1->correlation == file2->correlation )

   另外这里的结构也可以写得更简单些

if( file1->correlation == file2->correlation )  {   return 0;  }  if(file1->correlation > file2->correlation)  {   return 1;  }  return -1;

   sortfiles()函数像没用的裹脚布一样包在了qsort()上,使得qsort()的cmp实参变得不明不白。应该直接调用qsort()函数。

【样本】

 

while(true)    {        // 输入关键词…        // 计算关键词在各个文件中的词频        countkeyword(files,filecount,keyword);        // 按照关键词在各个文件中的词频,对文件进行排序        sortfiles(files,filecount);    }

 

  ——陈良乔 ,《C程序设计伴侣》,人民邮电出版社,2012年10月,p286

 【评析】

  非但笨拙,而且脱离了问题的要求。filecount和files毫无关联的错误同前,不再赘述。

转载地址:http://lrema.baihongyu.com/

你可能感兴趣的文章
WCF实例上下文模式与并发模式对性能的影响
查看>>
【C#学习笔记】窗口隐藏、最小化、最大化、正常化
查看>>
.NET 4.0 Beta2中的BigInteger和Complex类
查看>>
[Leetcode] Populating Next Right Pointers in Each Node
查看>>
由于客观原因,暂时学习php两天,然后继续学习.net
查看>>
30个免费下载高质量精美照片素材的网站(转)
查看>>
初学Linux
查看>>
Oracle Essbase入门系列(三)
查看>>
处理任务队列的工作线程的创建
查看>>
迎接互联网的明天--玩转3D Web
查看>>
心态成就财富
查看>>
TeeChart 4.0.2009.62335 不过期的方法
查看>>
云安全 安全领域的最大热点之一
查看>>
微软面试题:正则表达式提取链接地址
查看>>
Java MD5 加密加强版
查看>>
当时遇到的主要难点在于TextView的内容不会刷新改变值,今天终于通过Timer和Handler实现了,分享给大家...
查看>>
CentOS卸载系统自带的OpenJDK并安装Sun的JDK的方法
查看>>
二路归并排序 代码实例
查看>>
【转】理解 pkg-config 工具
查看>>
【转】Android中intent传递对象和Bundle的用法
查看>>