编程的六种武器

来源:百度文库 编辑:神马文学网 时间:2024/04/26 00:32:50
要学VB,需对其中的控件有一个系统的了解,因为有了他们,我们要做的程序的外表就有了。了解了控件的特点之后,VB的基础知识中的代码问题就成了非常重要的一个问题。我们的程序好比一个有机关的木偶,控件就是其中的外表各部件,代码就象其内部的机关。只有外表而没有机关,木偶就是死的;只有机关没有外表,那是幽灵或什么也不是;只有了解了外表后并据此做出了精明的机关,木偶就活了。
最基本的代码组成是什么呢?无非三大部分,三种语句,数组,函数或子程序,加上面向对象编程,类模块也应该算做一部分。下面我们将详细介绍他们。
下面将详细介绍顺序语句和工作程序
计算机中的所有工作都是按时间一件件一步步有条不紊地完成的,再复杂的工作也是如此的。
工作是怎样完成的呢,由一个个的具有某种功能的语句按时间先后顺序来完成,他们功能各不相同,有输入信息的:
a=1
也有输出信息的:
print a 或者 text1.text=str(a)。
当然这种语句太多了,VB中大部分语句都是。在这些语句中,赋值语句扮演了非常重要的角色。
顺序语句和赋值语句说明了计算机中的真谛。
稍稍有点编程思想的人士都知晓计算机的工作原理是:存储程序工作原理。要想存储,离不开赋值语句,是他使得这一原理成为了可能。计算机中的语句从功能上分有三种,输入,处理和输出,赋值对输入起着顶梁柱的作用,处理中也有众多的赋值语句参与运算。在三大功能中两大功能中是不可缺失的,作用不可谓不重要。
下面的案例最能说明赋值的作用:
(1)i=i+1
语句中的第一个i和第二个i是一个i,但其里面的东西却是不同的,第一个i比第二个i多1。这在数学上可是完全行不通的,可在计算机界,可以;并且因他的存在而精彩。
(2)两个同样大小的茶杯中盛有满满的两杯水,一个杯中是茶水,另一个杯中也是水,只不过是汽水,请将两杯水交换。
请思考。直接交换显然是不行的,除非我们会变戏法,象手里拿着三个帽子在头上和两手间轮换,不可能将第一个杯的水直接倒在第二个杯中,那不是我们所希望的结果。
仅仅只有两个杯子是怎么也不能完成的,我们需用第三只杯子。我们的工作可以 这么做:
第一步:将茶水倒入空杯中,使茶水杯先空出来;
第二步:将汽水倒入空出来的茶水杯中,现在汽水杯空出来了;
第三步:将第三只杯中的茶水倒入汽水杯中。
上面事实上就是程序,通过赋值(将水赋给或者说装入不同的杯子)运算来完成了我们的工作。同上面的过程进行对比,我们不难编出下面的小程:
示例:已知两个变量a,b,a的值为3,b的值为5,请将a,b的值交换。
a=3 ‘a为茶水杯
b=5 ‘b为汽水杯
c=a ‘第一步,c为空杯
a=b ‘第二步
b=c ‘第三步
print a,b ‘输出
从上面的两个简单的小例中您可能对赋值有了一定的理解。但第二个小例中很好地包含了工作程序的问题,其实这就是我们的编程,这也就是编程的真谛。可以不夸张地说,计算机中如果没有其它的东东,只有顺序语句,那一切可以照常工作;世界上万事万物虽然解决的方法不一定是一种,但只要将其分解得足够小,一定只有一种,那也就是一组有时间先后关系的顺序语句。但上面的两种可能其实又太不可行,也有点太麻烦了,有些工作简直不是人干的了,象让一个人在家中用笔写出一亿个“人”字一样,理论上可行而在现实中其实是不可行的。后面我们将详细介绍。
(以上程序在VB60下调试通过)
编程的六种武器
之二——分支语句:摸索前进的探路者
作者:赵玉勇
世界上万事万物解决的方法不一定是一种,真正要处理问题,也不可能将他们都有分成一个个的小问题然后解决。那怎么办呢?不要怕,因为语言中提供了分支语句,有了他们,我们就可在探索中前进了。
我们的工作不总是一成不变的,只要经过一二三四五等等的顺序就能完成,有时还有某些坎坷。可能的发展方向有好多,我们只能根据相应的条件来选择怎样向下工作。
如果您面对一个流言,您的态度有多种:理他还是不理他?所得的结果应该是不一样的,日子是不一样的,但仍然是要过下去的。上面的小事件可这么描述:
第一天发生了让他人说笑的事;
if 态度=理 then
招来更多烦恼,这一天过得象二十年
else
多几句空洞的说教,我们象他不存在一样过日子
end if
第三天,太阳依旧灿烂。
你可能想:这个语句中仅仅只有两种简单的情况,多种情况怎样表达?
这很简单,你只要在其中的语句中再嵌入一个相同的语句,三种情况就可解决。能解决三种,四种相信没问题,只要你有的种数,估计都能应付。
所以在使用这种语句时,还包含了多种结构。
这就是分支。还有一种处理多种情况更好的语句:
select x
case 1
case 2
...
case else
end select
这个分支语句可直接用来解决多种情况,但从上面我们也不难看出,多分支的条件太死板,太要求规律了,所以我们最好在使用的时候慎重一点。
分支可分为两大类,单分支和多分支。单分支也就是说问题的发展方向可能有两种,多分支语句说明可能的发展方向有三种或三种以上。
但分支的语句在VB中却有三种,上面列出了两种,他们都是“块”的形式,有开始,也有结束;其实单分支还有一种行的形式:
if   then   else
这种方式的作用和单分支的块的形式是完全一样的,只不过语句上看起来简洁一点,仅仅占用一行,但却缺乏直观,所以使用的时候要慎重,如果用它来塑造多分支时尤其要注意,最好使用块的形式。
小例:输入一个数,如果是非零的偶数,输出该数的三倍,如果是奇数,输出该数的三次方,如果是0,则输出88。
代码如下:
a = Val(Text1.Text)
If a = 0 Then
Print 88
Else
If Int(a / 2) = a / 2 Then
Print 3 * a
Else
Print a * a * a
End If
End If
上面的例程用了单分支语句的块的形式。我们说分支语句,其实仅仅是对框架来说的,框架内部仍然是起各种作用的顺序语句。
我们还需对上面的问题注意一点:即我们在编程时,无法知晓a的值究竟是什么,仅仅知道a是非负的整数而已。正是这种不确定性,使得我们后面的编程工作中对其进行了全方位思考,也就有了分支。
(以上程序在VB60下调试通过)
编程的六种武器
之三——循环语句:机械与机智的大师
作者:赵玉勇  付深义
其实循环又象是完全没有必要的。因为只要有了顺序语句和分支,一切问题处理起来就绰绰有余了。象我家的电话是2222222,您可以怎么描述呢?我们会说7个2。事实上循环的工作和上面的电话号码有些类似。我们通过尽量少的工作,去表示一个其实仍很完整的事例或意思。象我们下达这样的命令:让一个人在家中用笔写出一亿个“人”字,我们没必要这样下达,请你写“人”、“人”、......“人”(说了一亿个人)。
人是机智的,我们从事件中找出有利于我们工作的规律,让我们省事省力的干什么,计算机却仍然是老老实实地做了那么多工作。
我们最常用的一个例子是:求1+2+3+...+100的和
我们对本题的描述事实上是省略式的,我们向计算机的描述也是可以的(其中s表示和):
s=1
FOR i=2 TO 100
s=s+i
NEXT i
PRINT s
计算机真正做了99次加法运算。只不过他运算得太快,我们没有感觉到罢了。
循环语句主要有两大类,一种就是上面所列举的,其特点是循环次数确定,也就是中间的部分执行多少次编程的过程中我们就知晓了,另一种是循环次数不定的循环,或者也可以为循环多少次和我们的所求有直接的关系。下面的两个小例就说明了这样的问题,下面的两个小数学题目挺有意思的,简短的几句话,道出了循环的两大种类型。
示例1:40个小同学,相聚在一堂,相互击一掌,总计多少响?
示例2:一班小同学,相聚在一常,相互击一掌,780响,问多少相朋友,相聚在一堂?
上面的两个示例语句大体相同,但细细观看,它们的输入输出却正是截然相反的,前者的输入,正是后者的输出,前者的输出,却对应了后者的输入。由此我们得知其处理方法上应该是相似的,但又不是完全相同的。
这是个非常有意思的小题目。前者我们可用循环次数确定的循环解决,因为我们可找出人数和响数上的规律,有多少(n)个小同学,也即求1+2+3+...+(n-1)的和,所以第一个小例事实上就是让我们求1+2+......+40的和。
后面的示例呢?我们知晓也应该是40人,可怎样将规律仿出来呢?自然我们可以从1个人的情况一直向下寻找,但向下找不能是无限制的,需要有一个截止的条件,这就是780响。所以它的处理过程也是个循环,循环执行多少次我们不知道,但只要数量满足780响了,一切OK,我们就找到了那个和780响对应的数据了。
下面是示例2的代码(示例1的请参考上面的求和程序,一改就有了):
s = 0
i = 0
While s <= 780
s = s + i
i = i + 1
Wend
Print i
次数不确定的循环语句又可分为两种,一种是开始循环条件判断,另一种是结束循环条件判断。上面的小程序经过修改后如下:
s = 0
i = 0
Do
i = i + 1
s = s + i
Loop While s <= 780
Print i
其实三种类型的循环语句之间是完全相通的,上面的小程也可以用For循环做出,只不过其中需加上一个分支语句进行判断。
s = 1
For i = 2 To 100
s = s + i
If s = 780 Then
Print i + 1
End If
Next i
因为我们知晓规律是什么,我们虽不能准确地判断究竟是多少同学在班上,但范围我们是能肯定的,不是1人,也不是100人,但一定在1-100之间,所以我们就选择这个范围,将符合条件的那个输出出来了。
三种语句在这个程序中全有了,我们编程需做的是据问题的特点,选择一个最适合我们需用的。并且因为有了循环,使得问题更加复杂了,我们也可以更好地发挥自己的聪明才智了,让自己做尽量少的工作,而让计算机干最多的活计!
(以上程序在VB60下调试通过)
编程的六种武器
之四——数组:不可多得的规律机器
作者:赵玉勇  张久民
数组是一个非常好的可以看作工具一样的东西,并且数组和循环配合起来,干起活来让人心动,用规律机器来形容他真不为过。为什么要用数组呢?
我们首先来看一下数字在我们生活中的作用:一个我们无法回避的事实是,我们的生活中有许许多多的数字。我办公室是506,我在单位的代号是331,我的身份证号码是140104751209231等等,有了数字,好象是不便,其实还是给我们生活中带来了方便。到办公室找我,知道我在5楼,第6个房间,其他的数码各有自己的含义。
数字无疑给我们的生活带来了方便。
数组其实对我们来说非常有意思的有用的也是他们的数字,也就是他们的下标。数组有一维的,也有多维的。使用他们比较麻烦的一点是先要定义:dim a()。因为数组也有数字的优点,所以我们用数组。
下面的例子很能说明问题。
案例:一百个数,从大到小排序。
我们有一百个房间来放置一百个数,房间号为1-100,将来可将1号放最大的数字,二号放第二大的,...,100号放最小的。
怎样排序呢,只要将1号房间同后面的2,3,....,100进行比较,将大的数放到1号中,现在1号中一定是最大的数了;再将2号同3,4,5,...,100进行比较,现在2号放第二大的;...,将99号同100号比较,将大的放在99号,现在99号是第99大的,100号成了最小的了。
上面就是我们通过编号后找到的规律,数组就起到了这样的作用。我们可定义一数组a(100),a(1)表示第1号房间,a(2)表示第2号房间,...,a(100)表示第100号房间。上面的规律可描述如下:
FOR i=1 to 99
For j=i+1 to 100
IF a(i)d=a(i)
a(i)=a(j)
a(j)=d
END IF
NEXT j
NEXT i
正是因为有了数组,使得规律找出来了,也模拟出来了,退一步如果其中没有数组,也就是说没有下面的那几个数字,然后再编出程序来,那简直不可想象。如果再成为一百万个数呢,那简直是不可能的,但因为有了数组,所以在上面的代码上我们只要动个小手术,将99改成999999,将100改成1000000,一切OK。
在遇到非数字问题时,数组的作用就更大了。
题目:
大厅内有五个人,已知戴白帽子的说真话,戴红帽子的说假话,请据他们各自提出的线索辨别谁戴白帽子,谁戴红帽子。
甲:我看见一个戴白帽子的;
乙:我没看见一个戴红帽子的;
丙:我看见一个戴白帽子的;
丁:我没看见一个戴白帽子的;
戊:我的话和丙一样。
如何将上面的智力测验用程序编出呢?自然要用数组。
我们可以将五个人用一数组Cap(1)-Cap(5)来表示,将cap()设成两个值,T代表红帽,F代表白帽。这样一来,输出我们只要输出Cap(1)-Cap(5)的值就行了。
怎样将各种方案全部模拟出呢,有了数组,就容易组合了。可能的戴帽的情况有2X2X2X2X2=32种,应该是不算很多的,如果我们一种一种进行比较的话,恐怕那样子出来的一个顺序关系的程序也够吓人的。所以应该使用循环,整体上是循环。怎样将三十二种情况全部遍历呢?可以用五个循环,其中用Cap(1)-Cap(5)将各个循环的结果纳入,32种方案全部出炉。
For i = 0 To 1 ‘遍历所有可能戴帽方案
For j = 0 To 1
For k = 0 To 1
For l = 0 To 1
For m = 0 To 1
num = num + 1
cap(1) = i
cap(2) = j
cap(3) = k
cap(4) = l
cap(5) = m
Next m
Next l
Next k
Next j
Next i
有了全部的方案,我们只要用分支语句找出其中符合条件的就可以了。其他的东东,您可以自己向下瞧瞧。
这就是数组,有意思的数组。有了他,给我们的编程省去了不少麻烦。
数组中蕴含了规律,因为有数字,要发现他们,需要您开动脑筋了。
(以上程序在VB60下调试通过)
编程的六种武器
之五——函数、子程序与这其中的另类:递归
作者:赵玉勇 张宗顺
什么是函数、子程序
函数和子程序是我们经常用到的东东,函数有自定义的,也有系统附带的,但不管是自定义的还是系统的,他们都对相应的功能进行了封装,以利于我们经常性地使用。例如我们的对一个小数取整数INT()函数,不论什么样的小数,往()中一放,将来得到的值就自动将小数去除了。函数执行完将返回一个值,当然这个值可以是各种类型的,子程序仅仅执行一个过程,不返回数值。
1、随机函数RND
我们通过语言编程一般来说对事物的认识是很确定的了,是一就是一,是二就是二,还有一个问题,有一些不该那么确定的事情该如何处理,象我们的彩票抽奖,如果是确定的了,那也就不用抽了,恐怕也就没人玩了。对于这一类的事情,语言中提供了随机数,也就是说通过他得到的一个值将是不能确定的。但有一个范围。
Rnd 函数返回小于 1 但大于或等于 0 的值。
所以,当我们用到的值不在这个范围之内时,我们可以想点变通的办法。比如,我们想做一个猜1-100之间数的游戏,这个数只要这样表达就出来了:
INT(RND*100+1)
这个函数是非常有用的,他可能是计算机语言中唯一没有理性的东东了。就好象我们人类所具有的现省心的想法,妙手偶得之的佳句。正因为这个唯一性,也就不难看出他在计算机语言中的地位了。
2、和函数、子程序有非常密切关系的还有另一种奇妙的现象,递归。
递归究竟是什么东东呢?说白了它就象我们讲的那个故事:山上有座庙,庙里有个老和尚,老和尚在讲故事,它讲的故事是:山上有座庙,庙里有个老和尚,老和尚在讲故事,它讲的故事是:……也就是在一个函数中调用了其自身。就象上面的故事那样,故事中包含了故事本身。
下面就是对“老和尚讲故事”的定义:
案例:小猴吃枣
小猴第一天摘下若干枣子,当即吃掉了一半,不过瘾又多吃了一个;第二天吃了剩下的一半又多吃了一个;以后每一天都吃了前一天剩下的一半多一个。到第十天小猴再想吃时,见到只剩下一只枣子了。问第一天这堆枣子有多少?
从上题中我们可看到一个令人欣喜的规律,第十天为1,第九到第一天中后一天与1的和的两倍于前一天相等。下面就对这一规律做了描述:
Private Function monkey(ByVal x As Integer) As Integer
If x >= 10 Then
monkey = 1
Else
monkey = 2 * (monkey(x + 1) + 1)
End If
End Function
我们定义monkey()函数的时候通过monkey()自身来进行了定义,递归是个特殊的循环,是一个有着非常美妙的循环规则的循环。上题中我们只要将monkey(1),即第一天打印出来,一切OK。而这中间究竟是怎么工作的,我们可以不管。
要注意递归有时会了现栈溢出的问题,即递归的方法和老和尚讲故事的方法也是有区别的,只要老和尚知晓自己何时该不讲了,能收住声,递归也就成功了。以上程序在VB下运行成功。
3、API函数:Windows直通车
API(Application Program Interface,应用程序接口)函数调用是对Visual Basic功能的强有力扩充,它使得Visual Basic能够直接控制和处理计算机的系统参数和硬件资源。借助于API使得Visual Basic能克服Windows编程的难点,同时又增加供了使用Windows环境的灵活性。说他是Windows直通车一点也不为过,并且语言为我们提供了API文本浏览器,我们可以方便地对其进行调用。
利用Visual Basic调用API函数的方法方法非常简单:
(1)用Declare语句声明所要调用的API函数,若该函数无返回值,可声明为Sub过程;若有返回值,则可声明为Function函数;也可直接调用。
(2)一旦声明了某一个API函数后,就可以象调用Visual Basic的函数一样方便。在本程序中我们将函数的声明放在了一个模块中。
当然关于函数、子程序和他们之间发生的故事还有很多,我们仅仅列举了其中奇妙的几点,还有许多东东等着您的发现和利用。
(以上程序在VB60下调试通过)
编程的六种武器
之六——类模块:面向对象的利器
作者:赵玉勇
VB中的模块有两大类,一类是普通模块,另一类是类模块。普通模块可将我们用到的公共变量函数等的进行声明,使我们程序结构更加清晰,而类模块和他有着本质的区别。类模块是VB的面向对象编程强大功能的体现。
我们下面通过一个示例来具体地看看。
下面我们将建立一张链表。链表这种数据结构在VB中是没有直接提供的,所以需要我们自己构造。
要建立一个链表,必须首先确定组成链表的项目,象我们日常后活中的链条一样,链条是由一些小环组成的,并且这些小环有一个共同的特点,上面的和下面的存在着联系,我们建立一个链表类结构也是同样的道理,其最基本的单位是节点节点上要有和下一个节点相互联系的机制,所以定义链表比上面定义栈时要复杂一点,要用到两个类模块。
我们首先来构造具有上述特点的节点Node,然后通过节点来构造链表List。
(一)、节点的建立
我们可通过“工程”菜单中的“添加类模块”来建立一个名称为Node的节点,它是一个类模块,它包含两部分内容:
1、节点的内容,本题中是一个坐标信息:
Public X As Integer
Public Y As Integer
其中X表示横坐标,Y表示纵坐标
2、后续节点信息,通过它可对整个表中的节点进行链接
Public NextNode As Node
所以我们的节点类Node就建成了。
(二)、利用节点类构造链表类List
有了上面的Node节点类,也就有了组成链表的基本单位,我们可以构造自己的链表了。为了方便,我们仍然可以将链表的信息封装起来,组成一个新的类模块,名称为List。
我们首先在窗体上加上一文本框,以用来放链表的内容,然后通过“工程”菜单中的“添加类模块”来建立一个名称为List类模块。因为链表数据结构的建立是为了方便我们使用的,为了保证其在操作过程的完整性,其内容如下:
1、定义表头和表尾
Public ListHead As Node
Public ListTail As Node
表头和表尾是我们和链表进行交流的重要工具,他们也是节点类,各自具有节点的特点和自身的特点。
2、链表信息初始化
使一张链表初始化,表头也即表尾,并且均为空的。
Private Sub Class_Initialize()
Set ListHead = Nothing
Set ListTail = Nothing
End Sub
3、建立新节点
链表的节点需要我们一个一个去建立,将新的结点也就是Node类一个一个接入表中,接的方法就是通过对表头指针和表尾指针的调整。
Sub MakeNewNode(n1 As Integer, n2 As Integer)
Dim n As Node
Set n = New Node
n.X = n1
n.Y = n2
If ListHead Is Nothing Then
Set ListHead = n
Else
Set ListTail.NextNode = n
End If
Set ListTail = n
Set ListTail.NextNode = Nothing
End Sub
4、显示链表信息,可通过下面的方法实现
通过头指针和表建立联系,将指针信息不断修改后移,在实现表遍历的同时显示其中的内容。
Sub DisplayList()
Dim n As Node
Set n = ListHead
While Not n Is Nothing
Form1.Text1.Text = Form1.Text1.Text + "X:" + Str(n.X) + "Y:" + Str(n.Y) + vbCr + vbLf
Set n = n.NextNode
Wend
End Sub
5、清空链表内容,删除节点信息
Private Sub Class_Terminate()
ClearList
End Sub
Sub ClearList()
Dim n As Node
While Not ListHead Is Nothing
Set n = ListHead
Set ListHead = ListHead.NextNode
Set n = Nothing
Wend
End Sub
6、将一个表的内容传递到另一个表
Sub TransferList(list2 As list)
Set list2 = New list
Set list2.ListHead = ListHead
Set list2.ListTail = ListTail
Set ListHead = Nothing
Set ListTail = Nothing
End Sub
7、获取当前链表第一个节点信息,并将该节点清空
Sub GetNode(column As Integer, row As Integer)
Dim n As Node
If Not ListHead Is Nothing Then
Set n = ListHead
column = n.X
row = n.Y
Set ListHead = ListHead.NextNode
If ListHead Is Nothing Then Set ListTail = Nothing
Set n = Nothing
End If
End Sub
8、测试链表是空表还是非空表
Function HasNodes() As Boolean
HasNodes = Not ListHead Is Nothing
End Function
(三)、直接利用链表类进行面向对象编程
直接利用我们上面建立的链表类List,我们可很简单地完成上面已经构造的操作,当然我们在其中也可加入其他的方法。做为一个类,我们在使用它的过程中不必知道程序实现的细节问题,只要了解类本身具有的方法就可以应用了,不仅如此,我们可利用已有的类构造新的类,实现代码的可重用List就是在利用Node的基础上实现的。
下面的程序中很简单地实现了给链表添加10个节点,并将其内容在文本框中显示。下面的源程序非常简洁,我们上面的工作正是下面简洁的前提,在窗体上我们又加上了两个命令按钮,源程序如下所示:
Private Sub CmdChain_Click()
‘通过链表类来构造
Dim TestList As list
Dim i As Integer
Form1.ScaleMode = vbPixels
Form1.AutoRedraw = True
Set TestList = New list
Text1.Text = ""
For i = 1 To 10
TestList.MakeNewNode i, i * 10
Next i
TestList.DisplayList
End Sub
当然,我们在编程过程中也可以只通过节点来实现链表,当然节点之间的关系在我们使用起来时就应该很明了。
类模块是我们通过VB进行面向对象编程时不可缺少的部分,上面的三个类模块cStack是独立的,与后面的List和Node两者是没有任何关系的。但List和Node却有着密切的关系,如果没有后者,前者也不可能实现,他们象是子母的关系,抽象的程度不同,抽象越深,对后面我们的编程工作的工作量将越小,直接用List编程比只用Node要省事得多。其实还有更有趣的东东,类模块之间可以彼此定义。从中我想您不难体会面向对象编程的巨大内涵。
(以上程序在VB60下调试通过)