| 
|  |  
| jmsxdp 新手上路
 
  
 
 
 
 积分 12
 发帖 4
 注册 2010-3-9
 状态 离线
 | 
| 『楼 主』:
 用QB编译,可以在DOS全屏下显示汉字的小程序
 
[已使用 LLM 解释] 
 
 
下面是一段用QB编写的能在英文下显示汉字的小程序片断,可以运行,运行后会在全屏幕状态下显示汉字,程序利用的是UCDOS的16点阵汉字库,用兴趣可以试一下。这是很多年前用过的,拿出来大家分享。其实QB编的小程序很有用,现在本人还时常编一段,用来应付一些烦人的转换,例如将两个STR电影字幕文件合并到一起,等等等等....,说远了,奉上程序: '西文下显示汉字模块,需要文件UCDOS汉字库文件hzk16支持
 DECLARE SUB xshz16 (zf$)  '点阵坐标用,待显字符串
 DIM SHARED xsys
 DIM SHARED hzk$
 DIM SHARED er$
 ON ERROR GOTO erro
 er$ = "f"
 OPEN "b", #4, "HZK16"  '汉字库文件
 IF er$ = "t" THEN
 hzk$ = "f"
 END IF
 SCREEN 12
 xsys = 11              '字符颜色,数值为0-15,7:浅白,15:亮白,其他为彩色
 '                      '++++++以下添加需要程序++++++
 
 LOCATE 20, 1           '需要显示坐标
 zf$ = "显示汉字123ABC"     '显示的字符
 CALL xshz16(zf$)
 
 q:                     '程序退出
 SYSTEM
 
 erro:                 '错误处理
 errs = ERR
 er$ = "t"
 RESUME NEXT
 
 SUB xshz16 (zf$)        '显示汉字模块
 IF xsys = 0 THEN xsys = 15
 IF hzk$ = "f" GOTO hzkcl1
 l = LEN(zf$)
 zftmp$ = ""
 FOR i = 1 TO l
 m$ = MID$(zf$, i, 1)
 IF m$ = "1" THEN m$ = "1"
 IF m$ = "2" THEN m$ = "2"
 IF m$ = "3" THEN m$ = "3"
 IF m$ = "4" THEN m$ = "4"
 IF m$ = "5" THEN m$ = "5"
 IF m$ = "6" THEN m$ = "6"
 IF m$ = "7" THEN m$ = "7"
 IF m$ = "8" THEN m$ = "8"
 IF m$ = "9" THEN m$ = "9"
 IF m$ = "0" THEN m$ = "0"
 IF m$ = "q" THEN m$ = "q"
 IF m$ = "Q" THEN m$ = "Q"
 IF m$ = "w" THEN m$ = "w"
 IF m$ = "W" THEN m$ = "W"
 IF m$ = "e" THEN m$ = "e"
 IF m$ = "E" THEN m$ = "E"
 IF m$ = "r" THEN m$ = "r"
 IF m$ = "R" THEN m$ = "R"
 IF m$ = "t" THEN m$ = "t"
 IF m$ = "T" THEN m$ = "T"
 IF m$ = "y" THEN m$ = "y"
 IF m$ = "Y" THEN m$ = "Y"
 IF m$ = "u" THEN m$ = "u"
 IF m$ = "U" THEN m$ = "U"
 IF m$ = "i" THEN m$ = "i"
 IF m$ = "I" THEN m$ = "I"
 IF m$ = "o" THEN m$ = "o"
 IF m$ = "O" THEN m$ = "O"
 IF m$ = "p" THEN m$ = "p"
 IF m$ = "P" THEN m$ = "P"
 IF m$ = "
 
 " THEN m$ = "]"
 IF m$ = "}" THEN m$ = "}"
 IF m$ = "\" THEN m$ = "\"
 IF m$ = "|" THEN m$ = "|"
 IF m$ = "a" THEN m$ = "a"
 IF m$ = "A" THEN m$ = "A"
 IF m$ = "s" THEN m$ = "s"
 IF m$ = "S" THEN m$ = "S"
 IF m$ = "d" THEN m$ = "d"
 IF m$ = "D" THEN m$ = "D"
 IF m$ = "f" THEN m$ = "f"
 IF m$ = "F" THEN m$ = "F"
 IF m$ = "g" THEN m$ = "g"
 IF m$ = "G" THEN m$ = "G"
 IF m$ = "h" THEN m$ = "h"
 IF m$ = "H" THEN m$ = "H"
 IF m$ = "j" THEN m$ = "j"
 IF m$ = "J" THEN m$ = "J"
 IF m$ = "k" THEN m$ = "k"
 IF m$ = "K" THEN m$ = "K"
 IF m$ = "l" THEN m$ = "l"
 IF m$ = "L" THEN m$ = "L"
 IF m$ = ";" THEN m$ = ";"
 IF m$ = ":" THEN m$ = ":"
 IF m$ = CHR$(39) THEN m$ = "'"
 IF m$ = CHR$(34) THEN m$ = """
 IF m$ = "z" THEN m$ = "z"
 IF m$ = "Z" THEN m$ = "Z"
 IF m$ = "x" THEN m$ = "x"
 IF m$ = "X" THEN m$ = "X"
 IF m$ = "c" THEN m$ = "c"
 IF m$ = "C" THEN m$ = "C"
 IF m$ = "v" THEN m$ = "v"
 IF m$ = "V" THEN m$ = "V"
 IF m$ = "b" THEN m$ = "b"
 IF m$ = "B" THEN m$ = "B"
 IF m$ = "n" THEN m$ = "n"
 IF m$ = "N" THEN m$ = "N"
 IF m$ = "m" THEN m$ = "m"
 IF m$ = "M" THEN m$ = "M"
 IF m$ = "," THEN m$ = ","
 IF m$ = "<" THEN m$ = "<"
 IF m$ = "." THEN m$ = "."
 IF m$ = ">" THEN m$ = ">"
 IF m$ = "/" THEN m$ = "/"
 IF m$ = "?" THEN m$ = "?"
 IF m$ = "!" THEN m$ = "!"
 IF m$ = "@" THEN m$ = "@"
 IF m$ = "#" THEN m$ = "#"
 IF m$ = "$" THEN m$ = "$"
 IF m$ = "%" THEN m$ = "%"
 IF m$ = "^" THEN m$ = "︿"
 IF m$ = "&" THEN m$ = "&"
 IF m$ = "*" THEN m$ = "*"
 IF m$ = "(" THEN m$ = "("
 IF m$ = ")" THEN m$ = ")"
 IF m$ = "_" THEN m$ = "_"
 IF m$ = "+" THEN m$ = "+"
 IF m$ = "-" THEN m$ = "-"
 IF m$ = CHR$(32) THEN m$ = " "
 IF m$ = "~" THEN m$ = "~"
 IF m$ = CHR$(96) THEN m$ = "‘"
 IF m$ = "=" THEN m$ = "="
 zf1 = ASC(m$)
 IF zf1 < 160 THEN m$ = " "
 zftmp$ = zftmp$ + m$
 NEXT i
 zf$ = zftmp$
 hzbz = CSRLIN
 zzbz = POS(hzb)
 zzb = hzbz * 16 - 15
 hzb = zzbz * 8 - 7
 IF xsys = 0 THEN xsys = 7
 IF hzb = 0 THEN hzb = 1
 IF zzb = 0 THEN zzb = 1
 hzbtmp = hzb
 zzbtmp = zzb
 l = LEN(zf$)
 FOR i = 2 TO l STEP 2
 zf1$ = MID$(zf$, i - 1, 1)
 zf2$ = MID$(zf$, i, 1)
 zf1 = ASC(zf1$)
 zf2 = ASC(zf2$)
 no = ((zf1 - 160 - 1) * 94 + zf2 - 160 - 1) * 32 + 1
 SEEK #4, no
 cch$ = INPUT$(32, 4)
 FOR a = 1 TO 16
 ch1$ = MID$(cch$, a * 2 - 1, 1)
 ch2$ = MID$(cch$, a * 2, 1)
 ch$ = ch2$ + ch1$
 s = CVI(ch$)
 LINE (hzb, zzb)-(hzb + 15, zzb), xsys, , s
 zzb = zzb + 1
 IF zzb - zzbtmp = 16 THEN
 zzb = zzbtmp
 hzb = hzb + 16
 END IF
 NEXT a
 NEXT i
 GOTO xshz16subq
 hzkcl1:
 PRINT zf$
 xshz16subq:
 END SUB
 
 
 
 
LLM 解释
 代码背景与功能概述这段代码是用QuickBASIC(QB)编写的一个在英文DOS环境下显示汉字的小程序片段。它依赖于UCDOS的16点阵汉字库文件HZK16来实现汉字的显示。其主要功能是在DOS全屏模式(通过SCREEN 12设置屏幕模式)下,指定位置显示包含汉字和西文字符转换后的特定字符串。 代码详细分析
声明与变量初始化 DECLARE SUB xshz16 (zf$)  '声明一个子过程xshz16,参数为待显字符串zf$
DIM SHARED xsys
DIM SHARED hzk$
DIM SHARED er$
ON ERROR GOTO erro  '设置错误处理,当发生错误时跳转到erro标签处
er$ = "f"
OPEN "b", #4, "HZK16"  '以二进制读取模式打开汉字库文件HZK16
IF er$ = "t" THEN
    hzk$ = "f"
END IF
SCREEN 12  '设置屏幕模式为12,进入全屏状态
xsys = 11  '设置字符颜色,数值范围0 - 15,这里设置为11
 
DECLARE SUB用于声明自定义的子过程,方便后续调用。
DIM SHARED定义了共享变量,这些变量在整个程序的不同过程中都可以访问。
ON ERROR GOTO用于设置错误处理机制,当程序运行出现错误时,会跳转到erro标签处进行处理。
OPEN语句用于打开汉字库文件,以便后续读取汉字点阵信息。
SCREEN 12设置屏幕模式,使程序在全屏状态下运行。
xsys用于存储字符颜色值。
主程序部分 LOCATE 20, 1  '将光标定位到第20行第1列的位置
zf$ = "显示汉字123ABC"  '要显示的字符串
CALL xshz16(zf$)  '调用显示汉字的子过程xshz16来显示指定字符串
q:                     '程序退出标签
SYSTEM
 
LOCATE语句用于设置光标的位置,这里将光标定位到第20行第1列。
zf$定义了要显示的具体字符串内容。
CALL语句用于调用之前声明的xshz16子过程来显示字符串。
q:标签和SYSTEM语句用于程序的正常退出,SYSTEM会结束程序的运行。
错误处理部分 erro:                 '错误处理标签
    errs = ERR
    er$ = "t"
    RESUME NEXT
 
当程序运行出现错误时,erro标签处的代码会获取错误号(ERR),并将er$设置为"t",然后RESUME NEXT会使程序继续执行下一条语句。
显示汉字子过程xshz16 SUB xshz16 (zf$)        '显示汉字模块子过程
    IF xsys = 0 THEN xsys = 15
    IF hzk$ = "f" GOTO hzkcl1
    l = LEN(zf$)
    zftmp$ = ""
    FOR i = 1 TO l
        m$ = MID$(zf$, i, 1)
        '一系列西文字符到全角字符的转换逻辑
        zf1 = ASC(m$)
        IF zf1 < 160 THEN m$ = " "
        zftmp$ = zftmp$ + m$
    NEXT i
    zf$ = zftmp$
    hzbz = CSRLIN
    zzbz = POS(hzb)
    zzb = hzbz * 16 - 15
    hzb = zzbz * 8 - 7
    IF xsys = 0 THEN xsys = 7
    IF hzb = 0 THEN hzb = 1
    IF zzb = 0 THEN zzb = 1
    hzbtmp = hzb
    zzbtmp = zzb
    l = LEN(zf$)
    FOR i = 2 TO l STEP 2
        zf1$ = MID$(zf$, i - 1, 1)
        zf2$ = MID$(zf$, i, 1)
        zf1 = ASC(zf1$)
        zf2 = ASC(zf2$)
        no = ((zf1 - 160 - 1) * 94 + zf2 - 160 - 1) * 32 + 1
        SEEK #4, no
        cch$ = INPUT$(32, 4)
        FOR a = 1 TO 16
            ch1$ = MID$(cch$, a * 2 - 1, 1)
            ch2$ = MID$(cch$, a * 2, 1)
            ch$ = ch2$ + ch1$
            s = CVI(ch$)
            LINE (hzb, zzb)-(hzb + 15, zzb), xsys, , s
            zzb = zzb + 1
            IF zzb - zzbtmp = 16 THEN
                zzb = zzbtmp
                hzb = hzb + 16
            END IF
        NEXT a
    NEXT i
    GOTO xshz16subq
    hzkcl1:
        PRINT zf$
    xshz16subq:
END SUB
 
字符转换部分:
遍历输入的字符串zf$,将其中的西文字符转换为对应的全角字符(例如将1转换为1等),如果字符的ASCII码小于160(西文字符范围),则将其转换为全角空格 。
坐标计算部分:
通过CSRLIN获取当前行号hzbz,POS(hzb)获取当前列号zzbz,然后计算汉字显示的起始坐标zzb和hzb。
汉字点阵读取与显示部分:
对于每个汉字(每两个字符为一个汉字,因为汉字是双字节字符),根据汉字的区位码计算出在汉字库文件中的偏移位置no,然后通过SEEK定位到该位置,读取32字节的汉字点阵信息。接着遍历16行的点阵信息,将每个点按照指定的颜色xsys通过LINE语句绘制到屏幕上,从而实现汉字的显示。如果汉字库文件打开失败(hzk$ = "f"),则直接打印字符串。 技术细节与多种解决方案
屏幕模式设置:
QB中SCREEN语句用于设置屏幕模式,除了12模式外,还有其他模式可选,如0模式是文本模式等。如果要实现类似功能在不同屏幕模式下,需要根据不同模式的像素布局等调整坐标计算和绘制逻辑。
汉字库读取与显示:
这里依赖于特定的HZK16汉字库文件,其存储结构是按照16点阵汉字的区位码来组织的。如果要更换汉字库或者使用不同的存储结构,可以:
自定义汉字库的读取逻辑,根据新的汉字库格式解析汉字点阵数据。例如,如果使用不同编码的汉字库,可以重新编写根据汉字编码获取点阵数据的算法。考虑使用其他方式来存储和获取汉字点阵,比如将汉字点阵数据嵌入到程序中作为二进制资源,但这会增加程序体积。
错误处理的改进:
当前错误处理比较简单,只是记录错误号并继续执行下一条语句。可以改进为:
输出更详细的错误信息到屏幕或者文件中,方便调试。例如,在erro标签处添加代码将错误号和相关错误描述输出到指定位置。根据不同的错误类型采取不同的处理措施,而不仅仅是简单的继续执行。比如,如果是文件打开错误,可以提示用户检查汉字库文件是否存在等。 
 
 |  |  |  2010-4-6 10:43 |  |  |  |  
| jmsxdp 新手上路
 
  
 
 
 
 积分 12
 发帖 4
 注册 2010-3-9
 状态 离线
 |  |  |  2010-4-6 10:45 |  |  |  |  
| jmsxdp 新手上路
 
  
 
 
 
 积分 12
 发帖 4
 注册 2010-3-9
 状态 离线
 | 
| 『第 3 楼』:
 
 
[已使用 LLM 解释] 
 
 
另一个,这个不是把英文字母统统转化成中文字母,而是按原样显示: '西文下显示汉字模块,需要文件UCDOS汉字库文件hzk16支持
 DECLARE SUB xshz16 (zf$)  '点阵坐标用,待显字符串
 DIM SHARED xsys
 DIM SHARED hzk$
 DIM SHARED er$
 ON ERROR GOTO erro
 er$ = "f"
 OPEN "b", #4, "HZK16"  '汉字库文件hzk16
 IF er$ = "t" THEN
 hzk$ = "f"
 END IF
 SCREEN 12
 xsys = 14              '字符颜色0-15,7:浅白,15:亮白,其他为彩色
 '                      '++++++以下添加需要程序++++++
 
 LOCATE 20, 10           '需要显示坐标,为第20行10列
 zf$ = "显示1234;"     '显示的字符
 CALL xshz16(zf$)      '调用程序显示
 
 
 
 '                     '--------------添加部分结束-------------
 q:                     '程序退出
 SYSTEM
 
 erro:                 '错误处理
 errs = ERR
 er$ = "t"
 RESUME NEXT
 
 SUB xshz16 (zf$)        '显示汉字模块
 IF xsys = 0 THEN xsys = 14
 IF hzk$ = "f" GOTO hzkcl1
 l = LEN(zf$)
 hzbz = CSRLIN
 zzbz = POS(hzb)
 zzb = hzbz * 16 - 15
 hzb = zzbz * 8 - 7
 IF hzb = 0 THEN hzb = 1
 IF zzb = 0 THEN zzb = 1
 hzbtmp = hzb
 zzbtmp = zzb
 l = LEN(zf$)
 txtmp = 2
 xsmk1:
 FOR i = txtmp - 1 TO l
 zf1$ = MID$(zf$, i, 1)
 zf2$ = MID$(zf$, i + 1, 1)
 zf1 = ASC(zf1$)
 zf2 = ASC(zf2$)
 IF zf1 < 159 GOTO xsasc
 no = ((zf1 - 160 - 1) * 94 + zf2 - 160 - 1) * 32 + 1
 SEEK #4, no
 cch$ = INPUT$(32, 4)
 FOR a = 1 TO 16
 ch1$ = MID$(cch$, a * 2 - 1, 1)
 ch2$ = MID$(cch$, a * 2, 1)
 ch$ = ch2$ + ch1$
 s = CVI(ch$)
 LINE (hzb, zzb)-(hzb + 15, zzb), xsys, , s
 zzb = zzb + 1
 IF zzb - zzbtmp = 16 THEN
 zzb = zzbtmp
 hzb = hzb + 16
 END IF
 NEXT a
 i = i + 1
 NEXT i
 GOTO xshz16subq
 xsasc:
 LOCATE zzb / 16 + 1, hzb / 8 + 1
 PRINT zf1$
 txtmp = i + 2
 i = txtmp
 hzb = hzb + 8
 GOTO xsmk1
 hzkcl1:
 PRINT zf$
 xshz16subq:
 END SUB
 
 
LLM 解释
 代码功能概述这段代码是用QuickBASIC编写的一个在DOS全屏模式下显示汉字的小程序,依赖于UCDOS汉字库文件hzk16来实现汉字的显示。它定义了一个子程序xshz16来处理汉字的显示逻辑,同时有基本的屏幕初始化、错误处理等部分。 代码详细分析
变量定义与初始化
DECLARE SUB xshz16 (zf$):声明了一个名为xshz16的子程序,该子程序接受一个字符串参数zf$。
DIM SHARED xsys:定义了一个共享变量xsys,用于存储字符颜色相关的设置。
DIM SHARED hzk$:共享变量hzk$用于标记汉字库是否正常打开。
DIM SHARED er$:共享变量er$用于错误标记。
ON ERROR GOTO erro:设置错误处理,当程序发生错误时跳转到erro标签处。
er$ = "f":初始化错误标记为"f"(表示无错误)。
OPEN "b", #4, "HZK16":尝试以二进制模式打开汉字库文件HZK16。如果打开失败,er$会被设置为"t"。
SCREEN 12:将屏幕设置为全屏模式12,这是DOS下常见的全屏显示模式。
xsys = 14:设置字符颜色为14,这里0 - 15的数值对应不同的颜色,7是浅白,15是亮白等。
需要显示部分的代码
LOCATE 20, 10:将光标定位到第20行第10列。
zf$ = "显示1234;":定义要显示的字符串。
CALL xshz16(zf$):调用xshz16子程序来显示定义的字符串。
错误处理部分
erro标签处:获取错误号errs = ERR,并将er$设置为"t"(表示发生错误),然后继续执行下一条语句。
xshz16子程序
参数处理与初始化:
IF xsys = 0 THEN xsys = 14:如果字符颜色xsys被设置为0,则将其重置为14。
IF hzk$ = "f" GOTO hzkcl1:如果汉字库没有正常打开,则跳转到hzkcl1标签处,在hzkcl1标签处直接打印字符串(这种情况下可能无法正确显示汉字)。
字符串处理循环:
l = LEN(zf$):获取要显示字符串的长度。
hzbz = CSRLIN:获取当前光标的行号。
zzbz = POS(hzb):获取当前光标的列号相关计算值。
zzb = hzbz * 16 - 15和hzb = zzbz * 8 - 7:计算汉字显示的起始坐标相关值。进入循环xsmk1:
遍历字符串中的每个字符,对于每个字符,如果是西文字符(zf1 < 159),则直接在当前光标位置打印该西文字符;如果是汉字字符,则计算其在汉字库中的位置,读取对应的32字节汉字点阵信息,然后逐行逐列绘制汉字(通过LINE语句来绘制像素点,s = CVI(ch$)将两位十六进制字符转换为数值用于绘制)。 技术细节与多种解决方案汉字库访问方式
当前方式:通过OPEN "b", #4, "HZK16"以二进制模式打开汉字库文件,然后使用SEEK和INPUT$来读取汉字点阵数据。
其他解决方案:
可以考虑使用更高级的文件访问函数,比如在现代的DOS编程扩展环境中,可能有封装更好的库来访问汉字库。例如,可以使用一些DOS下的图形库相关函数来优化汉字的读取和显示流程,减少读取数据时的繁琐操作。 屏幕绘制
当前方式:使用LINE语句来绘制汉字的点阵像素,通过计算坐标来逐点绘制。
其他解决方案:
可以考虑使用更高效的图形绘制算法。例如,对于汉字点阵的绘制,可以预先将汉字点阵数据转换为更便于绘制的格式,或者利用一些图形库提供的批量绘制功能。比如,有些图形库可能支持直接根据点阵数据绘制字符块,而不需要逐点绘制,这样可以大大提高绘制效率。 错误处理
当前方式:简单地捕获错误并标记错误状态,然后继续执行。
其他解决方案:
可以增强错误处理机制,当发生错误时,不仅仅是标记错误状态,还可以向用户提供更详细的错误信息,比如弹出错误提示框(在DOS环境下可能需要通过特定的输出函数来实现),或者尝试自动恢复错误状态,比如重新打开汉字库文件等。 总的来说,这段代码实现了在DOS全屏模式下利用hzk16汉字库显示汉字和西文字符的基本功能,但在汉字库访问、屏幕绘制和错误处理等方面可以进一步优化和扩展。 
 
 |  |  |  2010-4-6 10:51 |  |  |  |  
| 070 高级用户
 
     苏醒的沉睡者
 
 
 积分 659
 发帖 217
 注册 2003-2-15
 来自 福建
 状态 离线
 | 
| 『第 4 楼』:
 
 
使用 LLM 解释/回答一下 
 
 
QB确实还挺有用的,就像写小工具,也是还可以用到20年前的Turbo c 
 
 
 
 
 |  
                  |  好久没碰Dos,手都生了,赶紧回来练练.嘿嘿
 |  |  |  2010-4-8 15:15 |  |  |  |  
| lqg2118 初级用户
 
   
 
 
 
 积分 36
 发帖 16
 注册 2010-6-30
 状态 离线
 |  |  |  2010-7-2 11:45 |  |  |  |  
| cnch 中级用户
 
    
 
 
 积分 326
 发帖 70
 注册 2003-1-10
 状态 离线
 |  |  |  2010-9-5 14:52 |  |  |  |  
| aq2007 初级用户
 
   
 
 
 
 积分 20
 发帖 9
 注册 2007-4-27
 状态 离线
 |  |  |  2010-10-29 00:23 |  |  |  |  
| lswd 初级用户
 
   
 
 
 
 积分 52
 发帖 25
 注册 2010-2-9
 状态 离线
 |  |  |  2020-2-7 14:06 |  |  |