199 发表于 2014-3-18 12:45:31

《C语言入门经典》一道课后题引出的编程思考

[ 本帖最后由 199 于 2014-3-18 12:56 编辑 ]

这几天在看《C语言入门经典》(Ivor Horton 第四版),大学四年中有两年半是扎扎实实的去玩了。玩够了大三下帮老师做项目,我就是打杂的,但是自己画了个51单片机的电路,以后想玩自己可以花钱请人打板。大四上考研,光荣战死。现在我像大一新生一样,每天要看C语言,C++,因为我毕业设计选了一个全校最牛,要求极其严格的老师。老人家教龄30多年,那个年代走过来的,要是我敢混, 非被这个老师一个键盘拍死。再加上以前玩得很有心得,这几天买了个超级不错的键盘,开始我正式的复习+预习程序学习之路,其实这个程序设计范围太大了,咱们就聊一道课后题,然后由这道课后题想到的,咱们慢慢说。

首先,这道题目是第六章习题6.2题目,我把要求大致复述一下:编写一个程序,输入一系列单词,单次之间以逗号分隔,然后提取这些单词,并将他们分行输出,删除头尾的空格。例如输入:
John,Jack,jill
输出将是:
John
Jack
Jill

题目分析:最怕出版商打印空格这些东西,你知道排版的时候很多空格就给搞丢了。所以,这个程序就不考虑空格了,直接考虑逗号‘,’的解决,说真的开始这个题目还真的要我耗费了一下脑筋。两种解法,第一种复杂些,抛砖引玉,这个就是砖,第二种解法就是玉。

解法1:写一个字符串数组,用于接收用户的输入;设计一个整形数组,用于统计字符串数组中逗号的序号(模块1)。然后以这些序号为基础,分为三类输出:把第一个逗号前的字符串输出(模块2-1);把第一个逗号和最后一个逗号之间的单词输出(模块2-2);把最后一个逗号以后的字符串输出(模块2-3)。 这些就是这个解法的思路了。直接上源代码和心得:

#include <stdio.h>
#include<string.h>
#include <ctype.h>

void main()
{
      char data;                                                                  //模块1
      int point;
      printf("Input your words less than 20 letters in total:\n");
      gets(data);
      int j=0;
      for (int i=0;i<20;i++)
      {
                if(data==',')
                        point=i;            
      }
/*
         for(int k=0;k<20;k++)
         {
                if(point <0 || point >20) point = 0;
               else
                         printf("%d ,",point);
         }
*/
      for(int m=0;m<point;m++) printf("%c",data);         //模块2-1
      printf("\n");
      int s=0;
      
      while(point)                                                                     //模块2-2
      {
                for(int n=point+1;n<point;n++)
                {
                        printf("%c",data);
                }   
                printf("\n");
                s++;
      }


      for(int last =0;last <20;last++)                                                       //模块2-3
      {
                if(point==0 && point>point)
      {
                for(int lastlast =point;lastlast<20;lastlast++)
                {
                        if (isalpha(data))
                              printf("%c",data);
                }
                printf("\n");
      }
      }
}



心得:(1)看不见的编程过程:除了你人生的第一个Hello World,很少有程序会只要求你只写一两行的代码了,那么对于我们来讲,不得不面对的问题是程序的调试,关于程序的调试,《C语言入门经典》中提到,编写了一个小功能的时候你就编译一下,不要写完了所有再一下子编译,那样会增加程序的死亡率。第一种解法中注释掉的第一处区域,其实是打印point数组,即逗号的位置,这个不是解法1的核心,但是确是该解法思路的基础,如果数组不对,下面你可以设置好自动关机,清理下垃圾,抽根烟,拿个快递了;所以这一步骤里面,我把point数组打印,尔后还给point中没有使用的空间赋值,这些都是打印了数组后方便下面的进行做的工作。(2)具体的调试过程:VC++6.0中提供了调试工具,以前老师就教我单步执行,查看寄存器,汇编代码等等。太复杂了,从来不用,就用printf来调试(只是当年那个老师的研究生助教交给我的)。这里面也有诸多技巧,即与你自己的想法有关,因为程序是你写的,你自己就会琢磨哪里用printf,哪里不需要用,需要输出什么等问题,一句话:自己做,自然会。(3)高聚合低耦合:C是非常适合模块化的语言,如果遇到合适的程序,那么完全可以看到C程序是由一个一个函数组成的;每个函数就完成一个单一的功能,不要一个函数完成很多功能,这个可以保证你的函数写好了,可以被其它人调用,比如下次要用,你直接拷贝过来就行了;(4)关于完美:很多人在做一件事情的时候,大多会想到自己利用时间把这件事情做到完美,很多同学也以完美主义者自居,我觉得如果你每次都做到了,你是大牛,如果你做不到,甚至什么都没做,那么就是浮躁。解决一个问题的时候,首先考虑的应该是如何把这个问题解决,解决了问题以后才考虑完美这个词,那时候你需要的是思考和改进。说真的,解决问题的最难的一点往往是问题的解决,即使你有思路,实现这个思路大多也是不易的。至于完美,在什么都没做的时候说就有点扯淡了。前几天看我同学大鹏的QQ签名:做完事情,要胜于完美收工。他已经工作了,实打实做的是项目,不是几十行代码的玩具,这就是经验。同样提出这种思想的还有《数学之美》那本书里面提到的艾利克·布莱尔(大牛,宾夕法尼亚大学马库斯实验室里待过),即简单之美,简单有效,我的思路略有不同,即直接暴力有效就行了。这个程序还能写得更好吗?能,我现在一个想法就可以给它来个大改,例如函数的使用,例如低耦合,但是有必要吗?没有,我要的是独立解决这个问题的过程,不看答案较劲脑汁把问题解决了。解决问题再付出的话就是写点东西留给自己看,也给大家一些思路,那些细枝末节的事情不要兼顾。


解法2:依旧是写一个字符串数组,接收用户的输入,然后打印该字符串数组,要是判断为字母,则打印该字母本身,如果是‘,’,则打印'\n',如果遇到空格等,不要操作,这样就完成了。


#include<stdio.h>
#include <ctype.h>
void main()
{
      char test;
      printf("Input your number:\n");
       gets(test);

      for(int i=0;i<20;i++)
      {
                if(isalpha(test) )
               {
                      printf("%c",test);
               }
                else if (test = ',')
                {
                        printf("\n");
                }
       else
      ;
   }
}


心得:(1)该程序的过程:吃了晚饭回来写的第二种解法,路上就在想,那个C语言不就是围着内存转吗?也就是一排一排的小房子,所以循环是少不了的。那么如何循环是一个问题,循环中干什么也是我该考虑的,我干嘛用那么多排房子存储不同的数据,直接在原始数据上循环,打印不就可以了吗?所以回来后哦很快就写好了。第一个if,判断是不是字幕,打印字母,如果你字符串里面有数字也要打印,加一个或语句,判断是不是数字if (isalpha(test) || isdigit(test))(你确定老美的名字有数字?美国版王二麻子?:titter:).第二个else if 判断是不是',',打印‘\n’,第三个else千万不要删掉啊,那是给空格等符号留着的,遇到这些啥也不要做,直接执行下次循环(continue?不清楚,自己试下呗)。(2)还有其他关于编程的思考,那是我这四年调皮捣蛋的经验,下次再说,下次再说。对了,学习写程序最重要的方法就是独立写,不要说我学完了集中写,能写就抓紧写,哪怕你看了一个自然段觉得有点心得需要表达。还有,千万不要背东西,这个就是一门手艺,就像游泳,骑马,不是你背了一本书就能体会的,如果算法什么的需要背下来,直接抄在txt文件里面,用的时候拿过来直接用。等你在一个语言泡久了,写程序基本上就是copy自己原来的程序了。当然,这也说明,你在做浪费时间的事情,该学习新的东西,让自己活力绽放吧。



mqweishijiunuli 发表于 2014-3-18 13:04:10

小白表示不太懂,大一,刚学习C语言入门。希望能有理解的那天哈哈!!!:big

199 发表于 2014-3-18 14:24:04

mqweishijiunuli 发表于 2014-3-18 13:04 static/image/common/back.gif
小白表示不太懂,大一,刚学习C语言入门。希望能有理解的那天哈哈!!!

共同学习!互相帮助!:handshake

abel 发表于 2014-4-21 10:38:32

感谢楼主分享
页: [1]
查看完整版本: 《C语言入门经典》一道课后题引出的编程思考