按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
如图10。5所示,树的每个结点中有个计数器,还有26个子结点指针,子结点指针根据单词中的下一个字母是A~Z分别指向不同的子结点,假如我们遇到一个单词“ver”,就为它创建4层结点,第1层结点中的第22个指针(代表V)指向第2层,第2层结点中的第5个指针(代表E)再指向第3层结点,同样第3层结点中第19个指针(代表R)指向第4层结点,并将第4层结点的计数中增加1表示遇到了一个“ver”单词。
如果遇到单词“very”,那么继续创建第5层结点,并将V…》E…》R结点下的第25个指针中(代表Y)指向这个第5层结点,同时将这个第5层结点的计数加1。
如果遇到一个单词“var”,那么在第2层结点中的A位置将出现一个分支指向另一个第2层结点。这样一来,数据树最大可能的深度就是单词的最大长度。
图10。5 WordCount程序中的内存结构
为结点定义了一个数据结构:
WORD_COUNT struct
lpLetter dd 26 dup (?)
dwCount dd ?
dwDepth dd ?
WORD_COUNT ends
结构中设置了26个指针用来指向下一层结点,分别代表下一个字母分别是A~Z的情况,如果没有下一个字母,则指针设置为NULL,dwCount字段用来计数。
每当程序遇到一个单词的开始字母,就从第1层结点开始处理,如果对应位置的指针已经存在,则继续移动下去,如果不存在,表示以前还没有遇到这样的单词,那么就新申请一块内存建立一个下层结点,依此顺序随着单词中的字母一层层处理下去,直到遇到单词结尾的时候在当前结点的计数上加1就可以了。
在输出结果的时候,程序用递归的方法遍历整个树,并将每个计数不是0的结点写到记录文件中。
这个程序灵活地使用了前面介绍的内存分配/释放函数,读者可以看到用汇编语言来处理比较复杂的数据结构也是比较方便的,源程序可以在所附光盘的Chapter10WordCount目录中找到。汇编源文件WordCount。asm的内容如下:
。386
。model flat; stdcall
option casemap :none
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
来源:电子工业出版社 作者:罗云彬 上一页 回书目 下一页
上一页 回书目 下一页
第10章 内存管理和文件操作
10。2 文 件 操 作(2)
; Include 文件定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
include windows。inc
include user32。inc
includelib user32。lib
include kernel32。inc
includelib kernel32。lib
include dlg32。inc
includelib dlg32。lib
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Equ 等值定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
ICO_MAIN equ 1000
DLG_MAIN equ 100
IDC_FILE equ 101
IDC_BROWSE equ 102
WORD_COUNT struct
lpLetter dd 26 dup (?)
dwCount dd ?
dwDepth dd ?
WORD_COUNT ends
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 数据段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
。data?
hInstance dd ?
hWinMain dd ?
szFileName db MAX_PATH dup (?)
szBuffer db 4096 dup (?)
stWordCount WORD_COUNT
dwCount dd ?
dwOption dd ?
F_COUNTING equ 00000001h
F_FILEEND equ 00000002h
nst
szFileExt db '全部文件';0;'*。*';0;0
szLogExt db '。log';0
szErrOpenFile db '无法打开文件!';0
szErrCreateFile db '无法建立记录文件!';0
szFmtWord db '%5d (%3d‰) %s';0dh;0ah;0
szSuccees db '统计成功,请查看记录文件%s';0
szSucceesCap db '统计成功';0
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 代码段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
de
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 遍历树并输出结果
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_WalkTree proc _hFile;_lpWC;_lpsz
local @dwTemp
local @szWord'52':byte
pushad
mov esi;_lpWC
assume esi:ptr WORD_COUNT
。if 'esi'。dwDepth && 'esi'。dwCount
;********************************************************************
; 计算百分比并写入log文件
;********************************************************************
mov eax;'esi'。dwCount
mov ecx;1000
mul ecx
mov ecx;dwCount
。if ecx
div ecx
。else
mov eax;0
。endif
invoke wsprintf;addr szBuffer;
addr szFmtWord;'esi'。dwCount;eax;_lpsz
invoke lstrlen;addr szBuffer
mov ecx;eax
invoke WriteFile;_hFile;addr szBuffer;
ecx;addr @dwTemp;NULL
。endif
;********************************************************************
; 如果有下层结点则递归调用
;********************************************************************
mov @dwTemp;0
。while @dwTemp 《 26
mov ebx;@dwTemp
mov ebx;dword ptr 'esi+ebx*4'
。if ebx
invoke lstrcpy;addr @szWord;_lpsz
invoke lstrlen;addr @szWord
lea ecx;@szWord
add ecx;eax
mov eax;@dwTemp
add al;'a'
mov word ptr 'ecx';ax
invoke _WalkTree;_hFile;ebx;addr @szWord
。endif
inc @dwTemp
。endw
;********************************************************************
; 释放结点
;********************************************************************
。if 'esi'。dwDepth
invoke GlobalFree;esi
。endif
popad
assume esi:ptr WORD_COUNT
ret
_WalkTree endp
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 如果输入的是字母则建立或移动到下一结点,输入0则增加结点计数
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_CountLetter proc _dwLetter
local @dwIndex
assume edi:ptr WORD_COUNT
or al;20h ;转换成小写字母
。if (al 》= 'a') && (al 》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
include windows。inc
include user32。inc
includelib user32。lib
include kernel32。inc
includelib kernel32。lib
include dlg32。inc
includelib dlg32。lib
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; Equ 等值定义
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
ICO_MAIN equ 1000
DLG_MAIN equ 100
IDC_FILE equ 101
IDC_BROWSE equ 102
WORD_COUNT struct
lpLetter dd 26 dup (?)
dwCount dd ?
dwDepth dd ?
WORD_COUNT ends
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 数据段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
。data?
hInstance dd ?
hWinMain dd ?
szFileName db MAX_PATH dup (?)
szBuffer db 4096 dup (?)
stWordCount WORD_COUNT
dwCount dd ?
dwOption dd ?
F_COUNTING equ 00000001h
F_FILEEND equ 00000002h
nst
szFileExt db '全部文件';0;'*。*';0;0
szLogExt db '。log';0
szErrOpenFile db '无法打开文件!';0
szErrCreateFile db '无法建立记录文件!';0
szFmtWord db '%5d (%3d‰) %s';0dh;0ah;0
szSuccees db '统计成功,请查看记录文件%s';0
szSucceesCap db '统计成功';0
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 代码段
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
de
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
; 遍历树并输出结果
;》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
_WalkTree proc _hFile;_lpWC;_lpsz
local @dwTemp
local @szWord'52':byte
pushad
mov esi;_lpWC
assume esi:ptr WORD_COUNT
。if 'esi'。dwDepth && 'esi'。dwCount
;********************************************************************
; 计算百分比并写入log文件
;********************************************************************
mov eax;'esi'。dwCount
mov ecx;1000
mul ecx
mov ecx;dwCount
。if ecx
div ecx
。else
mov eax;0
。endif
invoke wsprintf;addr szBuffer;
addr szFmtWord;'esi'。dwCount;eax;_lpsz
invoke lstrlen;addr szBuffer
mov ecx;eax
invoke WriteFile;_hFile;addr szBuffer;
ecx;addr @dwTemp;NULL
。endif
;********************************************************************
; 如果有下层结点则递归调用
;********************************************************************
mov @dwTemp;0
。while @dwTemp 《 26
mov ebx;@dwTemp
mov ebx;dword ptr 'esi+ebx*4'
。if ebx
invoke lstrcpy;addr @szWord;_lpsz
invoke lstrlen;addr @szWord
lea ecx;@szWord
add ecx;eax
mov eax;@dwTemp
add al;'a'
mov word ptr 'ecx';ax
invoke _WalkTree;_hFile;ebx;ad