在电子科大的第一次教学之实验5

在电子科大的第一次教学之实验5

问题集萃

简而言之,问题都不是内涵,都是些外围的东西。
附上我试验五完整代码

  1. 结构化程序设计

    • 老师对这个概念已经说过很多次了,但是至今我们还是不理解。像

       scanf("%d",&choice);
       switch (choice){
       case 1:Out_Put();
           break;
       case 2:Info_Change();
           break;
       case 3:Info_Insert();
           break;
       case 4:Info_Dele();
           break;
       case 5:Info_Search();
           break;
       case 6:Info_Flush();Free_Info();exit(0);
           break;
       default:Free_Info();exit(0);
           break;
       }
      

      这种一看就没有做到结构化设计。因为函数的实参是空的,返回值也是空的。这说明什么?函数没有做到高内聚松耦合,这就意味着一个函数做了太多事情。违背了 一个函数只做一件事 的原则。这样函数维护起来的成本就很高了。

    • 解决办法:一个函数做一件事,尽量不要在函数里面有scanf和printf。除非是专门的输出函数。

      int Search(int searchNumber, GoodsInfoBase *pGoodsInfoBase) {
       int i, ret = -1;
       for (i = 0; i < pGoodsInfoBase->partNum; i++) {
           if (pGoodsInfoBase->pGoodsInfoBase[i]->number == searchNumber) {
           ret = i;
           break;
           }
       }
       return ret;
       }
      
       ......
      
       Status PrintInfoOfAPart(int i, GoodsInfoBase *pGoodsInfoBase) {//专门的输出函数
       printf("   %d\t\t%s\t\t%d\t\t\t%g\n",
               pGoodsInfoBase->pGoodsInfoBase[i]->number,
               pGoodsInfoBase->pGoodsInfoBase[i]->partName,
               pGoodsInfoBase->pGoodsInfoBase[i]->onHand,
               pGoodsInfoBase->pGoodsInfoBase[i]->price);
       return OK;
       }
      
       ......
      
       case 's':
       printf("Enter part number: ");
       scanf("%d", &searchNumber);
       i = Search(searchNumber, &goodsInfoBase);
       if (i >= 0) {
           PrintInfoOfAPart(i, &goodsInfoBase);
       } else {
           printf("Part not found.\n");
       }
       break;
      
    • 提示:如果只想及格的话就没有必要做到这么严格,简洁一点反而看着舒服。

  2. 不要有全局变量表示商品的种类数。

    • 原因:这个不太好讲清楚。以我的经验看,以前我也是用的全局变量,
      但是在代码完全没报错的情况下,总是会出错。后来不用全局变量后就行了。

    • 解决办法:再建一个结构,这个结构里面包含 一个包含所有商品信息的结构数组(或指针数组)
      和 商品的种类。代码如下所示:

       typedef struct {
       int number;
       char partName[MAX_LEN + 1];
       int onHand;
       float price;
       } Part;
      
       typedef struct {
       Part *pGoodsInfoBase[MAX_GOODS];
       int partNum;
       } GoodsInfoBase;
      
    • 提示:就算你要用全局变量,也只需要在代码一开始定义一次就好了,没必要在每个函数中又重复定义

  3. 要注意语句间的对应关系

    • 比如:函数定义和函数调用中的形参和实参的类型要一致,比如不能一个是结构类型,一个是指针类型。如下:
      typedef struct goodsBase{
                   goodInfo goods[MAX];
                   int numOfGoods;
               }goodsBase;
      
               ......
      
       goodInfo *ReadGoodInfo(FILE *pf){
           goodInfo *pGoodInfo = (goodInfo *)malloc(sizeof(goodInfo));
           fscanf(pf,"%s",pGoodInfo->producingDate);
           fscanf(pf,"\t%s",pGoodInfo->name);
           fscanf(pf,"\t%s",pGoodInfo->price);
           fscanf(pf,"\t%s",pGoodInfo->discount);
           return pGoodInfo;
       }
      
       ......
      
       pGoodsBase->goods[j] = ReadGoodInfo(pf);
      
  4. 注意正确找到库函数来使用

    • 原因:库函数的意义就在于可以减少我们的开发成本。能熟悉库函数自然对我们十分有帮助。比如:
      productInfoBase.pProductArray[i]->name = newName;
      
      我们本意是想把一个字符串赋给另一个字符数组,但是这种写法虽然人看得明白,但是机器不明白。既然它是字符串的操作,所以我们应该想到<string.h>这个头文件。当我们去找时,会发现strcpy()这个函数刚好满足需求。
      strcpy(productInfoBase.pProductArray[i]->name,newName);
      
  5. 隐藏的错误(编译器不会报错)

    1. 文件名不是

      GoodsInfoBase.txt

      而是应该包含路径。比如:

      D:\GoodsIfoBase.txt

      除非你的文件和程序文件在同一个目录。

    2. 对于字符串数组,定义的时候一定要

      char name[MAX+1];
      

      这个 +1 一定不要少。这是规范问题,虽然不加而出错的概率比较小。原因我就不解释。

    3. scanf、fscanf等时,普通变量(char,int,float等)类型要用&,而数组用数组名就行,指针的话用*p.例如:

      fscanf(pProductFile, "%d\t%s\t%f\t",
         &(productInfoBase.pProductArray[i]->amount),
         productInfoBase.pProductArray[i]->name,
         &(productInfoBase.pProductArray[i]->price));
      
    4. 申请指针后一定要记得让指针指向一块内存(或变量)

      • 原因:很多人都容易犯这样的错误,在申请指针后没让指针指向一块内存(或变量),就马上对指针进行操作。正确做法:

         int a=9;
         int *p;
         p=&a;//不可缺
         printf("%d",*p);
        
        int *p;
        p=(int*)malloc(sizeof(int));//不可缺
        if(p==NULL){
            return ERROR;
        }
        *p=9;
        printf("%d",*p);
        
  6. 注意 C89C99 的区别

    • Cfree上是只支持C89的,如果在你的电脑上的编译器能运行的程序在cfree上不一定能运行。这里涉及到的最典型的例子就是bool类型。在C99中,只要
      #include<stdbool.h>
      
      就行。但是在C89中,你就必须
      typedef enum{YES=1,NO=0}Bool
      
      才行。
  7. 实验五具体几个函数的实现小细节

    1. delete函数不能仅仅对结构free一下就完事了。如果这样的话,你会发现在显示所有商品信息的操作中,显示到你刚刚删除的商品就停止了,还很可能直接退出程序。
      • 解决方案:如果是结构数组的话,就把删掉的那个结构后面的结构都向前挪一个位置;如果是指针数组的话,就把从你free的那个指针开始,每一个指针指向后面一个结构,最后一个指针再赋空。
    2. 在插入函数中,有时候会出现输入完编号后,后面的输入名字操作还没有做就调到下一个操作了。比如:
      printf("Enter part number: ");
      scanf("%d", &NewPart.number);
      printf("Enter part name: ");
      gets(NewPart.partName);
      printf("Enter quantity on hand: ");
      scanf("%d", &NewPart.onHand);
      printf("Enter price: ");
      scanf("%f", &NewPart.price);
      
      你输完part number后就直接跳过part name了。原因在于你输完part number读完part number后键盘缓冲区还剩一个 \n .所以下一个scanf就把换行符读了。
      • 解决方法: fflush()函数。它可以用来清除键盘缓冲区的内容。对应要使用<io.h>这个头文件。实现如下:
         printf("Enter part number: ");
         scanf("%d", &NewPart.number);
         fflush(stdin);
         printf("Enter part name: ");
         gets(NewPart.partName);
         printf("Enter quantity on hand: ");
         scanf("%d", &NewPart.onHand);
         printf("Enter price: ");
         scanf("%f", &NewPart.price);
        
        这个函数还有其他用处。比如在
        while(1){
         scanf("%d",&choice);
         switch (choice){
             case 1:Out_Put();
                 break;
             case 2:Info_Change();
                 break;
             case 3:Info_Insert();
                 break;
             case 4:Info_Dele();
                 break;
             case 5:Info_Search();
                 break;
             case 6:Info_Flush();Free_Info();exit(0);
                 break;
             default:Free_Info();exit(0);
                 break;
         }
        }
        
        中,如果不小心在
        scanf("%d",&choice);
        
        时输入了一大串东西,就会出现重复多次报错的情况。
        • 解决方案:
          while(1){
            scanf("%d",&choice);
            switch (choice){
                case 1:Out_Put();
                    break;
                case 2:Info_Change();
                    break;
                case 3:Info_Insert();
                    break;
                case 4:Info_Dele();
                    break;
                case 5:Info_Search();
                    break;
                case 6:Info_Flush();Free_Info();exit(0);
                    break;
                default:Free_Info();exit(0);
                    break;
            }
            fflush(stdin);
          }
          

总结

衣带渐宽终不悔,为C消得人憔悴

好了,就先讲到这把,好累了,明天上午还要上课。拜拜。最后送你们一张我老婆的壁纸!哇,精神瞬间充沛!
我老婆
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,723评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,485评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,998评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,323评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,355评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,079评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,389评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,019评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,519评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,971评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,100评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,738评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,293评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,289评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,517评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,547评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,834评论 2 345

推荐阅读更多精彩内容