zoukankan      html  css  js  c++  java
  • c语言用封装来优化程序

    一、基础研究

    先对函数fa进行研究,代码如下:

     

    fa函数的参数为一个字符指针,他存储要输出的字符串。因为要显示在屏幕的中央位置,所以我们要把字符串放在段地址b800处。用strlen获取字符串的长度,因为屏幕为2580列,所以如果字符串长度超过80,即一行放不下,那么就执行if后面的语句,这时要确保字符串整体位于屏幕中央,需要计算行数,而首地址的列数固定为3就可以了;如果字符串长度不超过80,即一行能够放得下,那么将字符串放在中间行第12行,而首地址的列数需要计算以确保字符串在屏幕中央,我们通过行数和列数计算字符串首地址时用(总行/列数-字符串占的行/列数(行加1列不加1))/2即可得出字符串首地址的行/列数。因为我们要在屏幕中央显示字符串,这样会覆盖掉屏幕上原来的信息,所以我们要提前将要显示的区域的信息保存起来,在我们的字符串现实之后,再将这些信息恢复。那么这些信息保存在哪里呢?保存在另一段内存中,因为传入的字符串长度是不确定的,所以要保存的屏幕信息的大小也是不确定的,我们无法先开辟一个固定的空间来保存它,只能动态地开辟空间来保存。所以我们需要使用malloc函数来动态地开辟空间,并将屏幕上的信息保存到这段内存中。这里传入的字符串长度为n,但是屏幕上一个字符是用2个字节来显示的,一个存储字符内容,一个存储颜色属性,所以我们在转移时转移的字节数应该是字符串长度的两倍。

    之后显示提示字符串并等待用户输入,直到用户输入了字符’y’,’Y’,’n’,’N’。之后将之前存储的屏幕信息还原并将按键信息返回。我们来看返回语句:returnch==y’||ch==’Y’);如果用户输入了’y’或’Y’,则这里会返回一个非0值,如果用户输入了’n’或’N’,则这里会返回0.

    再来看main函数是怎么使用fa函数的,代码如下:

     

    程序在调用fa函数时直接在里面传入了要显示的字符串,我们知道字符串是一个字符数组,而数组在作为参数时会退化成一个字符指针,所以可以与fa的参数类型对接。

    我们需要实现一个ask函数,ask函数实现的功能与fa函数相似,只是fa函数是实现所有功能,而ask函数是通过调用子函数实现具体功能。它们显示字符串、等待用户输入的功能是一样的。所以我们只需要修改fa最后的返回语句,改成用函数指针调用函数即可。程序如下:

     

    如果用户输入的是’y’,’Y’,则调用子函数,之后返回,如果用户输入的是’n’,’N’,则直接返回。

    我觉得ask所实现的特性是fa所实现的特性所衍生的。fa函数是用一个函数实现所有的功能,但是这样一个函数里面的代码太多了,会导致程序的维护性和可读性降低,所以askfa的基础上用子函数实现特定功能,这样修改和读起来都更加方便快捷。所以ask函数要比fa函数更好,因为它可以增加子函数对程序的功能进行扩展,而且函数的可读性和维护性更好。ask函数的设计思想是将函数的功能尽可能地细化,尽量做到每一个函数只实现一个功能,每一个函数的语句尽可能地少,最好在3句以内。这样可以将程序的可读性和维护行做到最好。

    我们将函数ask的代码加入到cs .lib中,这样我们要实现完整程序,只需要在c文件里写好子函数,再在main函数里调用就行了。 

    我们之前的封装是对共性的封装,这种封装到一定的程度就成了对对象的封装,这个时候我们对问题的抽象化已经到达了一定的程度,但是我们对对象的实例化与方法的调用等操作都是在main函数里的,也就是说我们对个性的实现主要是在main函数里,也就是我们对需求的实现主要是在main函数里。而且这些实现需求的语句是十分零碎杂乱的。要让程序更加有序,我们可以将需求的实现也封装起来,这样我们只需要在main函数里进行实例化和函数调用就可以了。而需求是需要函数来完成的,所以我们要把实现一个需求的语句封装在一个函数里,这样调用这个函数就可以实现需求。而fa函数是将实现需求的语句全部封装在函数内,而ask函数是将每一个小的需求都再封装在一个小的函数里,这样会使程序封装度更高,更加的有序。所以我们要使整个程序有序,不仅需要封装对象,也需要封装需求,不仅需要封装数据,也需要封装函数,即要做到数据、方法的有序,要做到所有函数内都是有序的,所有需求的实现都是有序的。

    二、扩展研究

    1、形如ch==’y’返回的bool型如果是非0值,是1还是有规律的数,如果不是1,是什么?

    答:由编译器的不同而不同,有的编译器的值是-1,有的是1.

    三、研究总结

    为了将程序的功能细化,我们可以每一个功能用一个函数实现,这样方便程序的测试、修改、扩展,做到了完全的有序化。事实上我们实现的这个ask函数还属于功能比较复杂的库函数,我们看printf函数、sizeof函数、kbhit函数、getch函数等,功能都非常单一,但是很实用,这样我们写程序时才能想的起来怎么用它们,如果你写了一个功能强大的库函数,要传入很多参数,实现很复杂的功能,但是实现大多数程序时都不适用,甚至你都想不起来该怎么用,这个函数就没有那些简单的、基本的库函数有价值。如果你实现的库函数可以表达我们某一种基本的需求,比如输出、输入、返回、调用等等,那么它才是有价值的。

    在比较简单的事物的基础上实现比较复杂的事物,这是比较简单的,在比较复杂的事物的基础上实现比较复杂的事物,这是比较难的。所以一个函数的功能要单一,我们才好用它。因为实现程序、表达思想的是程序员,不是我们调用的库函数,这些封装好的东西只是简化我们工作的,不是代替我们写程序的,它们只能算是一个个单词,是我们程序员把它们串联起来形成一条条语句,形成有特色功能的程序。

    而且我们写程序,不要把自己想的太聪明,而是要把自己往蠢里想,正是因为我们时时都有可能犯错,所以我们才要通过规范的程序设计思想来约束自己,正是因为每个人都时时可能犯错,所以才要通过法律、道德、各种价值观、人生观、世界观来约束自己,指导自己怎么去走正确的路,做对的事。

    程序设计思想就是指导我们在解决问题时采用合适的思路来分析和解决,而面向对象的程序设计思想能够让我们更好地认识问题,面向过程的程序设计思想能够让我们更好地解决问题。我们当然可以将这两种思想结合起来。而程序设计的关键点就是有序,为了实现这个目标,我们对程序进行各种层次和角度的封装,尽力使其在实现功能的基础上,变得更加有序、合理,便于扩展和组织,以方便我们借助程序对问题进行更深层次的思考。它的意义不仅在于让程序员更容易理解并进行扩展和修改,也在于借助于这个程序思考和解决问题。

  • 相关阅读:
    rsync
    2个网卡流量的变化
    服务器端FIN的条件
    The third column indicates whether subclasses of the class declared outside this package have access to the member.;
    Java反序列化与远程代码执行

    address sizes : 46 bits physical, 48 bits virtual
    intptr_t、uintptr_t数据类型的解析
    Why should we typedef a struct so often in C?
    源码 502 回溯
  • 原文地址:https://www.cnblogs.com/stormpeach/p/4366329.html
Copyright © 2011-2022 走看看