精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>● VB和Basic>>〓〓..技术文章连载..〓〓>>QB教程>>我的QB教程 (2)

主题:我的QB教程 (2)
发信人: whc()
整理人: fishy(2000-07-09 23:20:13), 站内信件
-  信区: PROGRAMR.CHINA  [程序人生]-----------------------------------

  信件: 2333                                         日期: 26 Oct 98  

11:30:44
  来自: Float Pointer                                已读: 是     已回

信 : 否 
    给: All                                          标记:            

         
  主题: FP的QB教程 第二篇
----------------------------------------------------------------------


在写教材时发现大家都喜欢实例教学,似乎直接把我的例子抄过
去学得最快最轻松.
因此我就多多举例. 不过读者最好购买一本QB的书,看附录
部分有详细的命令和函数的列表的那种就成,因为光举例子不可能
覆盖全面.如果你的英文还可以,也可以看QB的HELP,非常详细,
而且几乎每个例子都有一个example.

第一节其实还少说了点东西, 因为我太困忘了写. :)
--- 自定义数据类型:
象C语言的struct结构,QB也能用TYPE命令自己创造数据类型。如:

TYPE student         '定义一个“学生”类型
   sname AS STRING*8  'NAME是保留字不能用
   age AS INTEGER
   score as integer
END TYPE

在TYPE定义里不能有不定长字符串,只能用定长字符串。
TYPE的作用正是处理数据库!看上面这段定义象不象数据库的字段名?
如何打开和处理库文件我们以后再说。
定义完怎样使用呢?用DIM定义变量,用 变量名.字段名 引用:
 DIM stu as student
 stu.sname="小芳"

下面看一些例子:
例 2-1
--- ====================================
DEFINT A-Z
TYPE score
    sname AS STRING * 8
    chinese AS SINGLE
    math AS SINGLE
    english AS SINGLE
END TYPE

DIM a(10) AS score
i = 0
DO      'DO循环开始
   INPUT "姓名"; a(i).sname
   INPUT "分数:", a(i).chinese, a(i).math, a(i).english
   i = i + 1
LOOP UNTIL LTRIM$(a(i - 1).sname) = ""
'>LTRIM$函数是去掉字符串的前(LEFT)空格,因为sname是定长字符串,输入空
'>字符串也有8个空格. LOOP UNTIL表示循环直到后面表达式的值为"真".
FOR j = i - 2 TO 0 STEP -1   'FOR循环从I-2到0,"步长"每次减一.
   PRINT j; ":"; a(j).sname, a(j).chinese, a(j).math, a(j).english
NEXT
--- ====================================
按F5运行后先输入姓名,再输入分数,三个分数用逗号分割,必须写
三个数或输入空的逗号,否则会出错继续让你重新输入.
当不输入名字直接回车则停止,但还要输入两个逗号.最后按反序在屏幕上输出.


你会发现第一个INPUT自动加问号而第二个没有,因为第一个INPUT后跟一个分号,


而第二个后跟逗号.
※再看PRINT命令,PRINT命令也可用问号代替.在变量J和";",a(j).sname间
用分号连接,打印出来的内容就是紧挨着的,而后面用逗号连接,
QB自动按制表位置放置,每隔八个字符才打印一组数字.
而在每个PRINT命令行的最后,如果没有任何符号就会自动换行,
你甚至可以用一个空的PRINT表示多换一行。如果后面有分号或逗号,
那会影响到下一个PRINT命令的位置。

--- ☆ 表达式
QB的数学运算符有: 加+,减- ,乘* ,除 /,整除 \(截断小数部分),
取模 MOD, 乘方^.
比如上次我们那个画图的程序,循环由0到639,可颜色数只有16种(0-15)
因此我们用MOD运算.所谓取模就是求余数.
"怎么没有开方呀?"
有啊, X^.5 不就是对X开方么?(X的0.5次方)
怎样取倒数取平方也知道了吧,不过乘方的速度很慢,二次方最好用
X*X,取倒数最好用 1/x。
此外还有函数,跟数学上的函数概念差不多,比如在立即窗里输入:
  ? SIN(30)
哎?怎么不对呀?哦,原来用的是弧度,应该是
  ? sin(3.141592653589793*30/180)  'PI我背过50位呢。 ;)
运算优先级跟数学一样,括号优先,先函数,再乘方,先乘除,
然后MOD,再加减

QB里很重要的一种运算是逻辑运算。
1.关系运算:
         =  等于,当在赋值表达式里“=”表示赋值,但在表达
            式里代表判断是否等于,等于则为真(-1),否则为假(0)
         > 大于
         < 小于
>=  大于等于
         <= 小于等于
<>  不等于
关系运算可以比较数字或字符串。
字符串以ASCII值比较大小。
还记得上一篇所说的QB没有逻辑类型么? 试试
  ? 1=3
有什么结果. 你可以
  bool=1=2
结果bool得-1, 而bool可以是int,long甚至double类型

2.逻辑运算符
在QB里,逻辑运算符实际上是对变量逐位进行二进制运算的,有逻
辑运算和逻辑判断双重的作用。
逻辑操作符在数学上称做"布尔运算符"(boolean operator)
QB的HELP 里有关于它们的“真值表”

NOT 取非
AND 与
OR  或
XOR 异或
EQV 等价(同或)
IMP 蕴涵
前三个我就不说了,顾名思义么。
如果c=a XOR b,则当a=b时c得0,不相等为1
如果c=a EQV b,则..........1,........0
....... IMP ......a=1,b=0时c=0,否则c=1
如果A,B每个二进制位都是0或1,即A和B都为真(-1)或假(0),
那它的值必然也是-1(真)或0(假). 如果不为0或-1这两个数
则要用二进制一位一位的算(所有逻辑运算都是这样)
比如 4(100) xor 5(101) =1(001)  (括号里是二进制)
QB没有逻辑类型,我们通常用这个方法定真假:
  CONST False=0
  CONST True=NOT false '不假可不就是真么。 ;)
只有关系运算才返回的肯定是0或-1,其他逻辑运算除了值是0或-1,否则
一般都不是返回0、-1,而是按位运算的.

下面这是个把十进制数字转换成二进制数字的程序:
例 2-2
--- ====================================
DEFINT A-Z
INPUT a
FOR i = 15 TO 0 STEP -1 'INT是16位整数,二进制高位在前,因此倒序循环16


   IF a AND 2 ^ i THEN  '2的i次方就是二进制数第i位等于1的情况
      PRINT "1";
   ELSE
     PRINT "0";
   END IF
NEXT   '下一次循环
PRINT  '多换一行,否则下次运行时不好看,不信你把这行去掉试试。
--- ====================================
上面用了分行的IF命令,格式是
IF 表达式 THEN
   当为真(非0)时许多许多命令
ELSE
   当为假(等于0)时许多许多命令
END IF
也就是说IF a AND 2 ^ i THEN...和IF NOT((a AND 2 ^ i)=0) THEN
是等价的。
我们可以反复嵌套,比如
IF .... THEN
   IF ... THEN
      IF....
         ......
      END IF
   END IF
END IF
注意IF和END IF必须配对,否则会报错,因此最好象我这样用缩进格式。
包括循环语句也是,循环也可嵌套,为保证配对也最好用缩进格式。
 Q> 这些都是你自已想出来的还是书上说的,你给
 Q> 记住了.要是我自已想,哪想的出来啊. :(((
 Q> 这是不是就叫算法?我现在也没完全看明白.
 Q> 这可怎么学呀,一个一个的背?不是办法吧? :(((
A>当然是我自己编的了.我的教程里没有完全抄袭的程序,最多抄抄公式
A>和算法. :)
A>可以说这就是算法吧,编程需要较好的数学能力.比如从10进制转成二进制
A>的公式是用那个数反复除以2,把余数倒过来写,但这种方法只适用于手工计算.


A>二进制的特点是第0位表示0或1,第1位表示0或2,第三位表示0或4...第N位
A>表示0或2的N次方.
A>2^i正是代表要查的位,比如2^3=8,二进制是1000,AND是位运算,只有两边都是1


A>结果才也是1,比如二进制 10100 and 1000 =0 说明第三位是0,
A>如果11010 AND 1000 = 1000 不等于0 说明第三位是1.

在这里提一个系统函数:COMMAND$,没有任何参数。
它是命令行参数字符串。假如把上面这个程序的INPUT A换成
a=VAL(COMMAND$),VAL函数是把字符串转换成数字。
然后编译成EXE文件,假如叫做bin.exe,运行时打:
bin 2334 (回车)
你就能看到结果了,好象DOS命令一样,COOL吧。 :)
当然,不编译成EXE也可以看到效果的,在RUN菜单有一项可以修改COMMAND$
的值。

字符串运算只有加法,就是简单的把两个字符串连接在一起。
但QB的字符串函数非常丰富.比如下面这些常用函数:
下面都用实例来描述,直接在立即窗里输入就能看到效果.

VAL:
s$="3.1e-2": ? VAL(s$)
把S$字符串转换成数字变量.输出结果: .032

STR$:
?STR$(23)
把数字转换成字符串.是VAL的反函数.

CHR$
?chr$(7)
把数字转成相应的ASCII字符.

ASC()
?asc("a")
把字符转成ASCII码,是CHR$的反函数

LEN
LEN("12345")
返回字符长度。其实这个LEN可以返回任何变量的长度,包括自定义的TYPE。
在数据库读写中非常有用。

INSTR
?INSTR(1,"Ms Qbasic","basic")
搜索字符串,第一个数字是起始位置,可以省略。
如果返回0则是没找到。

UCASE$
?UCASE$("DdFd")
全改大写字母

LCASE$全改小写
LTRIM$去前导空格,RTRIM$去后面的空格。前面在例 2-1里已经说过。

HEX$是把十进制数转换成16进制字符串,比如 ?HEX$(255) 显示 FF
OCT$是................8 ..........
BIN$...没有这个函数啦,要你自己来编才成. ;)


发现了么?凡是反回字符串的函数总有个$,返回数字的就没有.
以后我们还能自己编函数和命令呢.

-3-
有了上面那些枯燥无味的基础,这一章我们就可以讨论点具体的了。

下面这个程序是个秒表,按任意键结束。
例 2-3
--- ====================================
t1 = TIMER
CLS  '清屏
COLOR 14, 1   '设置字符色为14(黄色),背景是1(兰色)
WHILE (INKEY$ = "")
   LOCATE 10, 20 '把光标移到 第10行,第20个字符的位置
   t2 = TIMER
   IF t2 < t1 THEN t1 = t1 - 24 * 60 * 60
PRINT t2 - t1
WEND
--- ============
TIMER函数是从午夜零点到现在的秒数,用来计时。
好象只要把当前时间与开始时间相减就成了,可是假如计时中
到了零点(咱们网友的习惯)怎么办?
IF语句判断是否过0点,如果过了就把开始时间减去一整天的时间(秒)。
这里的IF语句用的是单行IF命令。格式是:
IF 表达式 THEN 为真时命令 ELSE 为假时命令
其中的命令可以用冒号分隔使用多个命令。

INKEY$函数是我最喜欢的输入命令,它运行时读键盘缓冲区,如果没有字符
则返回空( "" 或者CHR$(0) ),有则返回字符.
如果是字母/数字返回的是ASCII码(可以查QB的HELP的CONTANTS有ASCII表)
需要知道的是,ESC是ASCII 27,BACKSPACE是8,ENTER是13,TAB是9,
如果PRINT CHR$(7)就会"滴"的一声响.
如果是控制键(比如光标键,PAGEUP等),返回的是两个字符长的字符串.
第一个是空(CHR$(0) ),第二个是IBM键盘扩展ASCII码,在HELP的
CONTANTS部分有KEYBOARD SCAN CODE表,键盘扫描码基本跟扩展ASC码一样.
比如你想判断输入的字符是否是键: IF INKEY$=CHR$(0)+CHR$(72) THEN...
很遗憾的是键盘扫描码不等于扩展ASCII码,QB里也没有,我的书里有.
如果你不知道可以编个程序一个一个实验各个键的码.
可以看出,INKEY$执行时不等待直接返回的这种性质可以编出象绘图,
动画控制,游戏等即时控制程序,非常有用.

关于LOCATE命令的格式是
LOCATE 行,列,光标是否可见,光标大小起始行,光标大小结束行
后面的都可以省略,尤其光标大小,很多显示卡都不支持。
而COLOR命令本还有一个参数是设置边框色,但QB有BUG,其实也不支持。
具体颜色代码请读者自己编个程序查查看,用两个FOR循环就成了
范围0-15

Q> t1 = t1 - 24 * 60 * 60
 Q> 还有这句,我凭自已想很难想出来这么写.
 Q> 是不是只能凭经验了?
A>当然不是,要经过你的思考.如何把生活中的事物表达成函数式也是一种能力.


A>就好象你把物理的应用问题转换成数学方程一样.
A>上面这个数是这样算出来的:
A>一天24小时,乘以一小时60分钟,乘以一分钟60秒. :)
A>有空给你看一个"万年历"的程序,非常著名.它的难点是把格里历转换
A>成公式,用BASIC居然一行就能完成了.
A>我以前编过一个叫BT(BatTool)的小软件, 里面就附带这个万年历程序.

下面就介绍一个比较实用的程序 - 破除SHAREWARE时间限制。
以前ZHANG TING前辈介绍过用QBASIC绕过CCDOS97时间限制的
方法。
实现的方法很多,下面是其中一种,可能与ZT的有点不同:
例2-4
--- ===========SAVEDATE.BAS ============
PRINT "DATE ";
PRINT DATE$
PRINT "DEL UPDATE.BAT"
DATE$="06-01-1997" '假设初次安装日期是97年6月1日
SYSTEM
--- ============CC.BAT==================
QBASIC /RUN SAVEDATE.BAS > UPDATE.BAT
CCDOS
rem 这里放输入法, 比如TWABC
UPDATE
--- ====================================
实际运行时运行CC.BAT就成了
BTW:此程序我未试过,我支持国产正版软件,至今仍用东方快车版。 :)
我想运行完应该给一个Batch file missing或者“批处理文件丢失”
的错误信息,但无关紧要。
上面这个例子介绍了DATE$函数和DATE$命令(名字都一样),类似的
还有TIME$函数和命令。
DATE$是个"违反常规"的函数,既可以取出日期,也可赋值修改日期.
DATE$="日期" 在QB的HELP里规定为"语句"而不是函数,
返回DATE$则规定为"日期函数".
TIME$函数你自己试试就知道了.
SYSTEM命令如果你用QBASIC或QB启动再OPEN程序运行,就跟END命令一样,
如果你在启动时用 QB /RUN XXX.BAS启动会自动运行BAS程序而不进入编辑界面.


而此时SYSTEM则能自动退出而不返回QB的编辑界面.
也就是说用上面的方法你用不着把程序编译成EXE也能执行,这也是
老式BASIC的运行方式.
上面那个程序如果编译成.EXE文件速度会快一些, 而且屏幕不会闪一下.

DOS命令QBASIC虽然只有QB的部分功能,但也能做不少事。
比如我的BWTE的前身就是用QBASIC+批处理的办法。


--- 现在复习一下分支语句。
QB的分支语句有IF,ON... GOTO和SELECT三种,最简单的IF语句是
IF 表达式 THEN 行号
行号有两种,一种是数字,比如

x=1:y=1
IF x=y then 20
END
20 ?20

但这个数字的大小是没有意义的,跟GWBASIC不同。
QB推荐使用字母行标号,与其他语言一样,比如

x=1:y=1
IF x=y then GOTO Label
END
Label: ? 20

不过GOTO命令最好不要单独使用,结构化编程不使用GOTO
连上面那样的转向语句最好也不用,直接用分行IF...END IF最好。
既然GOTO不好,ON...GOTO也就不说啦. :)
现在只有SELECT没有讲过了.看下面这个例子,可以实现菜单操作:
例2-5
--- ================
?"========================"
?" 0,E.什么都不干"
?" 1.列目录"
?" 2.改名"
?" 3,4,5.删除"
?"========================"
DO
  A$=INPUT$(1)       '从键盘读一个字符. 所谓"读"对于计算机来说就是输入

啦.
  SELECT CASE A$
       CASE "0","E"
            END
       CASE "1"
            SHELL "DIR /P"
       CASE "2"
            NAME "C:\AUTOEXEC.BAT" AS "A.BAK"
       CASE "3" TO "5"
            KILL "C:\COMMAND.COM"
       CASE IS > "Z"
           ?"输了个小写字母?"
       CASE ELSE
            ?"输入错误"
  END SELECT
LOOP  '没有任何条件参数的DO...LOOP循环是死循环.
--- ================
SELECT命令的条件除了可以用取值列表、取值范围外,还可以用IS变量,
IS代表初始条件值,就是A$啦。
INPUT$函数需要一个整数的参数,表示输入几个字符.
它直接读指定个数字的符,而且不在屏幕上显示.
END命令是结束命令,但可以省略,这样程序就由第一行运行到最后一行.
类似SYSTEM命令, 但不会自动退出.
SHELL命令是调用DOS命令. 如果没有参数就可以进入DOS方式,但QB程序
仍然在内存里,比如你在立即窗里输入SHELL,然后打MEM/C/P看看内存还剩多少.


返回是用DOS命令EXIT.如果有参数,当运行完参数里的程序后将会自动
返回.
NAME...AS命令相当于DOS命令REN,不过你可不要真的把AUTOEXEC.BAT给改没了. 

;)
KILL命令相当于DOS命令DEL. 哦,对了,仔细看看这个程序再运行,
可不要运行完了就启动不了计算机了. ;)

--- 最后,再总结一下QB的输入命令:
INPUT命令,想想分号和逗号的区别。如果INPUT后跟很多变量,
必须用逗号分隔每个变量。而且如果输入的是字符串,不能有逗号。
所以如果输入一行东西不如使用LINE INPUT。比如:
LINE INPUT A$
你可以输入任何字符,直到输入回车为止。当然CTRL-C和CTRL-BREAK不成。
a$=INPUT$(n) 函数是从键盘缓冲区里直接读n个字符,送到a$里,
如果A$=INPUT$(1)就相当于PRESS ANY KEY TO CONTINUE...了。
( Which key is "ANY KEY"? ;)  )
INKEY$函数每次都不等待直接从键盘缓冲区里读一个键,而且可以是
光标控制键。如果用户没有按键直接返回空字符。
无论是哪一种输入方法,QB都可能有汉字不能输入,比如“金”,
这是QB的BUG,如果你用的是MSBASIC 7就能解决问题了。

上面这些囫囵吞枣的灌给大家,恐怕记不住多少,应该
把所有例子都运行一遍,有点印象就好,编的时候再查书。
下次我就讲最吸引人的图形&动画. :)


...  ->  ==>>  ___whc.yeah.net____\    ┬──   ┬─┐
~~~  ->  ==>>  ___________________ `>  ├─     ├─┘
..>  ->  ==>>     [email protected]   /    ┴      ┴   

... press ALT-A key to continue...
--- GoldED/386   
 ! Origin: Beijing West-Point Porgrammer's BBS * 010-65233230 (6:650/2

7)


--------
  信件: 2333                                         日期: 26 Oct 98  
11:30:44
  来自: Float Pointer                                已读: 是     已回
信 : 否 
    给: All                                          标记:            
         
  主题: FP的QB教程 第二篇
----------------------------------------------------------------------
--------

在写教材时发现大家都喜欢实例教学,似乎直接把我的例子抄过
去学得最快最轻松.
因此我就多多举例. 不过读者最好购买一本QB的书,看附录
部分有详细的命令和函数的列表的那种就成,因为光举例子不可能
覆盖全面.如果你的英文还可以,也可以看QB的HELP,非常详细,
而且几乎每个例子都有一个example.

第一节其实还少说了点东西, 因为我太困忘了写. :)
--- 自定义数据类型:
象C语言的struct结构,QB也能用TYPE命令自己创造数据类型。如:

TYPE student         '定义一个“学生”类型
   sname AS STRING*8  'NAME是保留字不能用
   age AS INTEGER
   score as integer
END TYPE

在TYPE定义里不能有不定长字符串,只能用定长字符串。
TYPE的作用正是处理数据库!看上面这段定义象不象数据库的字段名?
如何打开和处理库文件我们以后再说。
定义完怎样使用呢?用DIM定义变量,用 变量名.字段名 引用:
 DIM stu as student
 stu.sname="小芳"

下面看一些例子:
例 2-1
--- ====================================
DEFINT A-Z
TYPE score
    sname AS STRING * 8
    chinese AS SINGLE
    math AS SINGLE
    english AS SINGLE
END TYPE

DIM a(10) AS score
i = 0
DO      'DO循环开始
   INPUT "姓名"; a(i).sname
   INPUT "分数:", a(i).chinese, a(i).math, a(i).english
   i = i + 1
LOOP UNTIL LTRIM$(a(i - 1).sname) = ""
'>LTRIM$函数是去掉字符串的前(LEFT)空格,因为sname是定长字符串,输入空
'>字符串也有8个空格. LOOP UNTIL表示循环直到后面表达式的值为"真".
FOR j = i - 2 TO 0 STEP -1   'FOR循环从I-2到0,"步长"每次减一.
   PRINT j; ":"; a(j).sname, a(j).chinese, a(j).math, a(j).english
NEXT
--- ====================================
按F5运行后先输入姓名,再输入分数,三个分数用逗号分割,必须写
三个数或输入空的逗号,否则会出错继续让你重新输入.
当不输入名字直接回车则停止,但还要输入两个逗号.最后按反序在屏幕上输出.

你会发现第一个INPUT自动加问号而第二个没有,因为第一个INPUT后跟一个分号,

而第二个后跟逗号.
※再看PRINT命令,PRINT命令也可用问号代替.在变量J和";",a(j).sname间
用分号连接,打印出来的内容就是紧挨着的,而后面用逗号连接,
QB自动按制表位置放置,每隔八个字符才打印一组数字.
而在每个PRINT命令行的最后,如果没有任何符号就会自动换行,
你甚至可以用一个空的PRINT表示多换一行。如果后面有分号或逗号,
那会影响到下一个PRINT命令的位置。

--- ☆ 表达式
QB的数学运算符有: 加+,减- ,乘* ,除 /,整除 \(截断小数部分),
取模 MOD, 乘方^.
比如上次我们那个画图的程序,循环由0到639,可颜色数只有16种(0-15)
因此我们用MOD运算.所谓取模就是求余数.
"怎么没有开方呀?"
有啊, X^.5 不就是对X开方么?(X的0.5次方)
怎样取倒数取平方也知道了吧,不过乘方的速度很慢,二次方最好用
X*X,取倒数最好用 1/x。
此外还有函数,跟数学上的函数概念差不多,比如在立即窗里输入:
  ? SIN(30)
哎?怎么不对呀?哦,原来用的是弧度,应该是
  ? sin(3.141592653589793*30/180)  'PI我背过50位呢。 ;)
运算优先级跟数学一样,括号优先,先函数,再乘方,先乘除,
然后MOD,再加减

QB里很重要的一种运算是逻辑运算。
1.关系运算:
         =  等于,当在赋值表达式里“=”表示赋值,但在表达
            式里代表判断是否等于,等于则为真(-1),否则为假(0)
         > 大于
         < 小于
>=  大于等于
         <= 小于等于
<>  不等于
关系运算可以比较数字或字符串。
字符串以ASCII值比较大小。
还记得上一篇所说的QB没有逻辑类型么? 试试
  ? 1=3
有什么结果. 你可以
  bool=1=2
结果bool得-1, 而bool可以是int,long甚至double类型

2.逻辑运算符
在QB里,逻辑运算符实际上是对变量逐位进行二进制运算的,有逻
辑运算和逻辑判断双重的作用。
逻辑操作符在数学上称做"布尔运算符"(boolean operator)
QB的HELP 里有关于它们的“真值表”

NOT 取非
AND 与
OR  或
XOR 异或
EQV 等价(同或)
IMP 蕴涵
前三个我就不说了,顾名思义么。
如果c=a XOR b,则当a=b时c得0,不相等为1
如果c=a EQV b,则..........1,........0
....... IMP ......a=1,b=0时c=0,否则c=1
如果A,B每个二进制位都是0或1,即A和B都为真(-1)或假(0),
那它的值必然也是-1(真)或0(假). 如果不为0或-1这两个数
则要用二进制一位一位的算(所有逻辑运算都是这样)
比如 4(100) xor 5(101) =1(001)  (括号里是二进制)
QB没有逻辑类型,我们通常用这个方法定真假:
  CONST False=0
  CONST True=NOT false '不假可不就是真么。 ;)
只有关系运算才返回的肯定是0或-1,其他逻辑运算除了值是0或-1,否则
一般都不是返回0、-1,而是按位运算的.

下面这是个把十进制数字转换成二进制数字的程序:
例 2-2
--- ====================================
DEFINT A-Z
INPUT a
FOR i = 15 TO 0 STEP -1 'INT是16位整数,二进制高位在前,因此倒序循环16

   IF a AND 2 ^ i THEN  '2的i次方就是二进制数第i位等于1的情况
      PRINT "1";
   ELSE
     PRINT "0";
   END IF
NEXT   '下一次循环
PRINT  '多换一行,否则下次运行时不好看,不信你把这行去掉试试。
--- ====================================
上面用了分行的IF命令,格式是
IF 表达式 THEN
   当为真(非0)时许多许多命令
ELSE
   当为假(等于0)时许多许多命令
END IF
也就是说IF a AND 2 ^ i THEN...和IF NOT((a AND 2 ^ i)=0) THEN
是等价的。
我们可以反复嵌套,比如
IF .... THEN
   IF ... THEN
      IF....
         ......
      END IF
   END IF
END IF
注意IF和END IF必须配对,否则会报错,因此最好象我这样用缩进格式。
包括循环语句也是,循环也可嵌套,为保证配对也最好用缩进格式。
 Q> 这些都是你自已想出来的还是书上说的,你给
 Q> 记住了.要是我自已想,哪想的出来啊. :(((
 Q> 这是不是就叫算法?我现在也没完全看明白.
 Q> 这可怎么学呀,一个一个的背?不是办法吧? :(((
A>当然是我自己编的了.我的教程里没有完全抄袭的程序,最多抄抄公式
A>和算法. :)
A>可以说这就是算法吧,编程需要较好的数学能力.比如从10进制转成二进制
A>的公式是用那个数反复除以2,把余数倒过来写,但这种方法只适用于手工计算.

A>二进制的特点是第0位表示0或1,第1位表示0或2,第三位表示0或4...第N位
A>表示0或2的N次方.
A>2^i正是代表要查的位,比如2^3=8,二进制是1000,AND是位运算,只有两边都是1

A>结果才也是1,比如二进制 10100 and 1000 =0 说明第三位是0,
A>如果11010 AND 1000 = 1000 不等于0 说明第三位是1.

在这里提一个系统函数:COMMAND$,没有任何参数。
它是命令行参数字符串。假如把上面这个程序的INPUT A换成
a=VAL(COMMAND$),VAL函数是把字符串转换成数字。
然后编译成EXE文件,假如叫做bin.exe,运行时打:
bin 2334 (回车)
你就能看到结果了,好象DOS命令一样,COOL吧。 :)
当然,不编译成EXE也可以看到效果的,在RUN菜单有一项可以修改COMMAND$
的值。

字符串运算只有加法,就是简单的把两个字符串连接在一起。
但QB的字符串函数非常丰富.比如下面这些常用函数:
下面都用实例来描述,直接在立即窗里输入就能看到效果.

VAL:
s$="3.1e-2": ? VAL(s$)
把S$字符串转换成数字变量.输出结果: .032

STR$:
?STR$(23)
把数字转换成字符串.是VAL的反函数.

CHR$
?chr$(7)
把数字转成相应的ASCII字符.

ASC()
?asc("a")
把字符转成ASCII码,是CHR$的反函数

LEN
LEN("12345")
返回字符长度。其实这个LEN可以返回任何变量的长度,包括自定义的TYPE。
在数据库读写中非常有用。

INSTR
?INSTR(1,"Ms Qbasic","basic")
搜索字符串,第一个数字是起始位置,可以省略。
如果返回0则是没找到。

UCASE$
?UCASE$("DdFd")
全改大写字母

LCASE$全改小写
LTRIM$去前导空格,RTRIM$去后面的空格。前面在例 2-1里已经说过。

HEX$是把十进制数转换成16进制字符串,比如 ?HEX$(255) 显示 FF
OCT$是................8 ..........
BIN$...没有这个函数啦,要你自己来编才成. ;)


发现了么?凡是反回字符串的函数总有个$,返回数字的就没有.
以后我们还能自己编函数和命令呢.

-3-
有了上面那些枯燥无味的基础,这一章我们就可以讨论点具体的了。

下面这个程序是个秒表,按任意键结束。
例 2-3
--- ====================================
t1 = TIMER
CLS  '清屏
COLOR 14, 1   '设置字符色为14(黄色),背景是1(兰色)
WHILE (INKEY$ = "")
   LOCATE 10, 20 '把光标移到 第10行,第20个字符的位置
   t2 = TIMER
   IF t2 < t1 THEN t1 = t1 - 24 * 60 * 60
PRINT t2 - t1
WEND
--- ============
TIMER函数是从午夜零点到现在的秒数,用来计时。
好象只要把当前时间与开始时间相减就成了,可是假如计时中
到了零点(咱们网友的习惯)怎么办?
IF语句判断是否过0点,如果过了就把开始时间减去一整天的时间(秒)。
这里的IF语句用的是单行IF命令。格式是:
IF 表达式 THEN 为真时命令 ELSE 为假时命令
其中的命令可以用冒号分隔使用多个命令。

INKEY$函数是我最喜欢的输入命令,它运行时读键盘缓冲区,如果没有字符
则返回空( "" 或者CHR$(0) ),有则返回字符.
如果是字母/数字返回的是ASCII码(可以查QB的HELP的CONTANTS有ASCII表)
需要知道的是,ESC是ASCII 27,BACKSPACE是8,ENTER是13,TAB是9,
如果PRINT CHR$(7)就会"滴"的一声响.
如果是控制键(比如光标键,PAGEUP等),返回的是两个字符长的字符串.
第一个是空(CHR$(0) ),第二个是IBM键盘扩展ASCII码,在HELP的
CONTANTS部分有KEYBOARD SCAN CODE表,键盘扫描码基本跟扩展ASC码一样.
比如你想判断输入的字符是否是键: IF INKEY$=CHR$(0)+CHR$(72) THEN...
很遗憾的是键盘扫描码不等于扩展ASCII码,QB里也没有,我的书里有.
如果你不知道可以编个程序一个一个实验各个键的码.
可以看出,INKEY$执行时不等待直接返回的这种性质可以编出象绘图,
动画控制,游戏等即时控制程序,非常有用.

关于LOCATE命令的格式是
LOCATE 行,列,光标是否可见,光标大小起始行,光标大小结束行
后面的都可以省略,尤其光标大小,很多显示卡都不支持。
而COLOR命令本还有一个参数是设置边框色,但QB有BUG,其实也不支持。
具体颜色代码请读者自己编个程序查查看,用两个FOR循环就成了
范围0-15

Q> t1 = t1 - 24 * 60 * 60
 Q> 还有这句,我凭自已想很难想出来这么写.
 Q> 是不是只能凭经验了?
A>当然不是,要经过你的思考.如何把生活中的事物表达成函数式也是一种能力.

A>就好象你把物理的应用问题转换成数学方程一样.
A>上面这个数是这样算出来的:
A>一天24小时,乘以一小时60分钟,乘以一分钟60秒. :)
A>有空给你看一个"万年历"的程序,非常著名.它的难点是把格里历转换
A>成公式,用BASIC居然一行就能完成了.
A>我以前编过一个叫BT(BatTool)的小软件, 里面就附带这个万年历程序.

下面就介绍一个比较实用的程序 - 破除SHAREWARE时间限制。
以前ZHANG TING前辈介绍过用QBASIC绕过CCDOS97时间限制的
方法。
实现的方法很多,下面是其中一种,可能与ZT的有点不同:
例2-4
--- ===========SAVEDATE.BAS ============
PRINT "DATE ";
PRINT DATE$
PRINT "DEL UPDATE.BAT"
DATE$="06-01-1997" '假设初次安装日期是97年6月1日
SYSTEM
--- ============CC.BAT==================
QBASIC /RUN SAVEDATE.BAS > UPDATE.BAT
CCDOS
rem 这里放输入法, 比如TWABC
UPDATE
--- ====================================
实际运行时运行CC.BAT就成了
BTW:此程序我未试过,我支持国产正版软件,至今仍用东方快车版。 :)
我想运行完应该给一个Batch file missing或者“批处理文件丢失”
的错误信息,但无关紧要。
上面这个例子介绍了DATE$函数和DATE$命令(名字都一样),类似的
还有TIME$函数和命令。
DATE$是个"违反常规"的函数,既可以取出日期,也可赋值修改日期.
DATE$="日期" 在QB的HELP里规定为"语句"而不是函数,
返回DATE$则规定为"日期函数".
TIME$函数你自己试试就知道了.
SYSTEM命令如果你用QBASIC或QB启动再OPEN程序运行,就跟END命令一样,
如果你在启动时用 QB /RUN XXX.BAS启动会自动运行BAS程序而不进入编辑界面.

而此时SYSTEM则能自动退出而不返回QB的编辑界面.
也就是说用上面的方法你用不着把程序编译成EXE也能执行,这也是
老式BASIC的运行方式.
上面那个程序如果编译成.EXE文件速度会快一些, 而且屏幕不会闪一下.

DOS命令QBASIC虽然只有QB的部分功能,但也能做不少事。
比如我的BWTE的前身就是用QBASIC+批处理的办法。


--- 现在复习一下分支语句。
QB的分支语句有IF,ON... GOTO和SELECT三种,最简单的IF语句是
IF 表达式 THEN 行号
行号有两种,一种是数字,比如

x=1:y=1
IF x=y then 20
END
20 ?20

但这个数字的大小是没有意义的,跟GWBASIC不同。
QB推荐使用字母行标号,与其他语言一样,比如

x=1:y=1
IF x=y then GOTO Label
END
Label: ? 20

不过GOTO命令最好不要单独使用,结构化编程不使用GOTO
连上面那样的转向语句最好也不用,直接用分行IF...END IF最好。
既然GOTO不好,ON...GOTO也就不说啦. :)
现在只有SELECT没有讲过了.看下面这个例子,可以实现菜单操作:
例2-5
--- ================
?"========================"
?" 0,E.什么都不干"
?" 1.列目录"
?" 2.改名"
?" 3,4,5.删除"
?"========================"
DO
  A$=INPUT$(1)       '从键盘读一个字符. 所谓"读"对于计算机来说就是输入
啦.
  SELECT CASE A$
       CASE "0","E"
            END
       CASE "1"
            SHELL "DIR /P"
       CASE "2"
            NAME "C:\AUTOEXEC.BAT" AS "A.BAK"
       CASE "3" TO "5"
            KILL "C:\COMMAND.COM"
       CASE IS > "Z"
           ?"输了个小写字母?"
       CASE ELSE
            ?"输入错误"
  END SELECT
LOOP  '没有任何条件参数的DO...LOOP循环是死循环.
--- ================
SELECT命令的条件除了可以用取值列表、取值范围外,还可以用IS变量,
IS代表初始条件值,就是A$啦。
INPUT$函数需要一个整数的参数,表示输入几个字符.
它直接读指定个数字的符,而且不在屏幕上显示.
END命令是结束命令,但可以省略,这样程序就由第一行运行到最后一行.
类似SYSTEM命令, 但不会自动退出.
SHELL命令是调用DOS命令. 如果没有参数就可以进入DOS方式,但QB程序
仍然在内存里,比如你在立即窗里输入SHELL,然后打MEM/C/P看看内存还剩多少.

返回是用DOS命令EXIT.如果有参数,当运行完参数里的程序后将会自动
返回.
NAME...AS命令相当于DOS命令REN,不过你可不要真的把AUTOEXEC.BAT给改没了. 
;)
KILL命令相当于DOS命令DEL. 哦,对了,仔细看看这个程序再运行,
可不要运行完了就启动不了计算机了. ;)

--- 最后,再总结一下QB的输入命令:
INPUT命令,想想分号和逗号的区别。如果INPUT后跟很多变量,
必须用逗号分隔每个变量。而且如果输入的是字符串,不能有逗号。
所以如果输入一行东西不如使用LINE INPUT。比如:
LINE INPUT A$
你可以输入任何字符,直到输入回车为止。当然CTRL-C和CTRL-BREAK不成。
a$=INPUT$(n) 函数是从键盘缓冲区里直接读n个字符,送到a$里,
如果A$=INPUT$(1)就相当于PRESS ANY KEY TO CONTINUE...了。
( Which key is "ANY KEY"? ;)  )
INKEY$函数每次都不等待直接从键盘缓冲区里读一个键,而且可以是
光标控制键。如果用户没有按键直接返回空字符。
无论是哪一种输入方法,QB都可能有汉字不能输入,比如“金”,
这是QB的BUG,如果你用的是MSBASIC 7就能解决问题了。

上面这些囫囵吞枣的灌给大家,恐怕记不住多少,应该
把所有例子都运行一遍,有点印象就好,编的时候再查书。
下次我就讲最吸引人的图形&动画. :)


...  ->  ==>>  ___whc.yeah.net____\    ┬──   ┬─┐
~~~  ->  ==>>  ___________________ `>  ├─     ├─┘
..>  ->  ==>>     [email protected]   /    ┴      ┴   

... press ALT-A key to continue...
--- GoldED/386   
 ! Origin: Beijing West-Point Porgrammer's BBS * 010-65233230 (6:650/2
7)

--
※ 修改:.whc 于 Jul  2 21:37:47 修改本文.[FROM: 202.106.214.190]
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.106.214.190]

[关闭][返回]