




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
1、文本編輯器文本編輯器是最常用的文檔創(chuàng)建和編輯工具。 隨著計算機(jī)科學(xué)與 技術(shù)的發(fā)展,用來處理文本的編輯器隨處可見,并且形式多樣。比如,Windows下的記事本,寫字板,EditPlus,UltraEdit 等都 是十分優(yōu)秀的文本編輯器和處理工具。 在本章中, 我們將向讀者 講解如何利用C語言來發(fā)展開發(fā)一個簡易的文本編輯器。1設(shè)計目的利用C語言的單鏈表數(shù)據(jù)結(jié)構(gòu)及相關(guān)函數(shù),本章編程實現(xiàn)了 一個與DOS操作系統(tǒng)下的Edit相似的文本編輯器。再次文本編 輯器中, 用戶可以通過快捷和選擇菜單項, 完成基本的文本編輯 器和文件處理工作。通過文章的介紹, 讀者可以了解文本編輯器的開發(fā)過程, 掌 握菜單的開發(fā)技
2、巧,加深對文件操作的理解。更重要的是,希望 此程序能拋磚引玉, 引領(lǐng)讀者掌握編程的方法和技巧, 開發(fā)出更 優(yōu)秀的程序。2 功能描述如圖 .1 所示,文本編輯器主要由五大功能模塊構(gòu)成,它們 分別是文件操作模塊,文本編輯模塊,剪切操作模塊,菜單控制 模塊和幫助及其他模塊。下面分別簡要介紹功能模塊的功能。(1)文件操作模塊。在文件操作模塊中,主要完成文件的 創(chuàng)建,打開,保存和另存操作。 用戶可以選擇 File 菜單上的 New 子菜單來完成新建文本文件操作; 選擇 File 菜單上的 Save 子菜 單來完成保存文件操作選擇 File菜單上的Open子菜單來完成打 開文件操作; 選擇 Flie 菜單
3、上的 Saveas 子菜單來完成文件的另 存為操作。在文件的打開,保存和另存為操作中,系統(tǒng)會提示用 戶輸入文件路徑及文件名。 值得一提的是, 當(dāng)用戶打開一個文件 時,指定的文件必須存在,否則系統(tǒng)會報錯。(2)文本編輯器模塊。在文本編輯器模塊中,主要完成在 編輯窗口中以添加或插入的方式輸入字符, 刪除光標(biāo)所在當(dāng)前位 置的單個字符或前一個位置的單個字符, 朝上下左右 4 個方向的 光標(biāo)移動操作。 當(dāng)光標(biāo)所在位置及后面的位置沒有字符時, 系統(tǒng) 會以添加的方式輸入字符; 當(dāng)光標(biāo)所在位置及后面的位置有字符 時,系統(tǒng)會已插入的方式輸入字符。用戶可以使用Backspace鍵刪除光標(biāo)前一個字符, 也可以使用
4、Del 鍵刪除當(dāng)前位置的字符或 刪除 Ctrl+ 左移(右移)鍵 i 選定了的多個字符。用戶可以使用 左移鍵(J),右移鍵(f),上移鍵(T)和下移鍵(J)來移 動光標(biāo)位置。( 3)剪貼板操作模塊。在剪貼板操作模塊中,主要完成對 已選定文本的剪切,復(fù)制,粘貼工作。如果用戶要剪切文本以便 可以將它移動到其他位置,可通過 Ctrl+X 左移鍵(右移鍵)先 選定文本, 然后選擇 Edit 菜單上的 Cut 子菜單或按 Ctrl+X 快捷 鍵來完成剪切任務(wù)。 如果用戶要復(fù)制文本以便可以將它黏貼到其 他位置,必須先選定文本,然后選擇Edit菜單上的Copy紫菜單 或按 Ctrl+C 快捷鍵來完成復(fù)制任務(wù)
5、。如果用戶要粘貼剪切或復(fù) 制的文本,必須將光標(biāo)置于要粘貼文本的位置,然后選擇 Edit 菜單上的 Paste 子菜單或按 Ctrl+V 快捷鍵來完成粘貼任務(wù)。(4)菜單控制模塊。在菜單控制模塊中,主要完成菜單的 顯示。光帶條在子菜單之間的上下移動或菜單之間的左右移動和 子菜單項的選取。 本文本編輯器共有 Flie,Edit 和 Help3 個子菜 單項,用戶可以分別按 F1,F2和F3功能鍵來完成這3個菜單項 的調(diào)用, 即顯示某項菜單。 用戶可按光標(biāo)上移或下移鍵在某菜單 項的子菜單之間循環(huán)移動, 也可使用光標(biāo)的左移或右移鍵在 3 個 菜單項之間循環(huán)移動。 當(dāng)光帶移動到某個字菜單項上時, 用戶此
6、 時可使用 Enter 鍵來選取相關(guān)菜單選項。(5)幫助及其他模塊。在幫助及其他模塊中,主要完成系 統(tǒng)功能及按鍵的簡要介紹。 其他模塊包括文本的快速預(yù)覽和窗口 的顯示。用戶可按 F 1 0功能鍵來打開快速預(yù)覽窗口,在快速預(yù)覽窗口中沒有功能菜單條。 主窗口要有菜單欄, 文本編輯區(qū)和狀態(tài) 欄三大部分構(gòu)成, 菜單欄用來顯示菜單項, 文本編輯區(qū)主要用來 文本字符的輸入, 刪除等操作, 狀態(tài)欄主要用來顯示當(dāng)前光標(biāo)在 文本窗口中的坐標(biāo)值。注意:TurboC2.默認(rèn)定義的文本窗口為整個屏幕,共有 80列(或40列),25行的文本單元,每 個單元包括一個字符和一個屬性,字符即 ASCII 碼字符,屬性規(guī)定該字
7、符的顏色和強(qiáng)度。同時,他還規(guī)定 整個屏幕的左上角坐標(biāo)為(1,1),右下角坐標(biāo)為(80,25)。并規(guī)定沿水平方向為 X軸,方向朝右;眼垂 直方向為Y軸,方向朝下。3總體設(shè)計3.1 功能模塊設(shè)計在.2 節(jié)中,簡單描述了各功能模塊的作用,下面分別介紹 各功能模塊的具體設(shè)計。 在介紹各功能模塊的具體設(shè)計之前, 有 必要先描述一下主程序的執(zhí)行流程。1. 程序執(zhí)行主流程文本編輯器程序執(zhí)行主流程如圖 .2 所示,它是在 main() 函數(shù)中實現(xiàn)的。 他首先初始化一些全局變量及結(jié)構(gòu)數(shù)組, 接著調(diào) 用 drawmain() 函數(shù)來顯示主窗口,然后調(diào)用 while(1) 進(jìn)入主循 環(huán),等待用戶按鍵,最后程序根據(jù)用
8、戶的按鍵值,進(jìn)行相應(yīng)的處 理,完成文本編輯的相關(guān)工作。下面對圖 .2 中的按鍵判斷和相 關(guān)處理作補(bǔ)充說明。(1)若按鍵為常規(guī)字符,即其 ASCII 碼大于 32 小于 127, 則繼續(xù)判斷在文本編輯區(qū)的當(dāng)前光標(biāo)位置有沒有字符,若有字 符,則調(diào)用 insert() 函數(shù),將此字符插入在當(dāng)前位置,否則在 判斷沒有滿行后, 將此字符添加在單鏈表的數(shù)據(jù)域中, 若此行已 滿,則執(zhí)行添加新行操作。(2) 若按鍵為 Enter 鍵,則將光標(biāo)移至下一行的行首,等 待用戶輸入新的字符。(3) 若按鍵為光標(biāo)移動鍵(左,右,上,下)且移動后的 位置滿足相關(guān)條件,則執(zhí)行 gotoxy() 操作,將光標(biāo)移動至目標(biāo) 位置
9、。(4)若按鍵為 BackSpace 鍵,則將調(diào)用 Del() 函數(shù)將光標(biāo) 的前一個字符從單鏈表中刪除; 若按鍵為 Del 鍵,也將調(diào)用 del() 函數(shù)將光標(biāo)的當(dāng)前位置的字符從單鏈表中刪除。(5)若按鍵為 Ctrl 開頭的按鍵,則執(zhí)行與其相關(guān)的操作。具體來說,若為 Ctrl+左移鍵(),則將選定當(dāng)前光標(biāo)的位置 開始向右的一個字符,若按住 Ctrl 鍵不放,連續(xù)按右移鍵,可 以選定多個字符。若為Ctrl+左移鍵(),則將執(zhí)行與以上相同的操作。若為 Ctrl+X 鍵,則將選定相關(guān)內(nèi)容保存起來,且從 單鏈表中刪除選定的字符后重新顯示單鏈表的內(nèi)容。 若為 Ctrl+C 鍵,則將選定的相關(guān)內(nèi)容保存起來
10、, 重新顯示單鏈表中的內(nèi)容 (目 的:為了去除字符的底色) 。若為 Ctrl+V 鍵,則調(diào)用 insert() 函數(shù)將保存起來的字符插入在單鏈表中, 并重新顯示單鏈表中的 內(nèi)容。( 6)若按鍵為 F10 鍵,則調(diào)用 qview() 函數(shù),實現(xiàn)文本的 快速預(yù)覽。若按鍵為 F1,F2,F3 功能鍵,則調(diào)用 menuctrl() 菜單控制函數(shù), 在此函數(shù)中完成案件的具體判斷和執(zhí)行相應(yīng)功能操作。若為 F1 鍵,則調(diào)用 File 菜單;若為 F2 鍵,則調(diào)用 Edit 菜單;若為 F3 鍵,則調(diào)用 Help 菜單。2文件操作模塊 在此模塊中,主要實現(xiàn)文件的新建、打開、保存和另存為操作。 在此系統(tǒng)中, 文
11、件的新建操作實現(xiàn)比較簡單, 文件另存為操作與 保存操作類似, 下面重點介紹在此文本編輯器程序中, 文件的打 開和保存操作的具體設(shè)計和實現(xiàn)。 在介紹之前, 我們先簡單描述 一下程序中用到的保存數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。 在此程序中, 共有兩種 類型的單鏈表, 我們稱其為行單鏈表和列單鏈表, 一個列單鏈表 用來保存一行的字符, 有多少行即有多少個這樣的單鏈表。 行單 鏈表只有一個, 它的每個節(jié)點的數(shù)據(jù)域用來保存不同列單鏈表的 首節(jié)點的地址。 例如,第 4 行第 4 列的字符保存在行單鏈表的第 4 個節(jié)點的數(shù)據(jù)域所指的列單鏈表的第 4 個節(jié)點的數(shù)據(jù)域中。有 關(guān)具體數(shù)據(jù)結(jié)構(gòu)的定義,在后面的小節(jié)中會有具體介紹。1
12、)打開文件文件的打開流程如圖 .3 所示,它首先提示用戶輸入要打開文件 的文件名, 若該文件不存在或由于其他原因打開失敗, 則會結(jié)束 文件打開操作。 若文件成功打開并且文件指針沒有到文件尾, 則 從文件中一次讀取一個字符, 并將該字符添加到一列單鏈表節(jié)點 中,直至遇到換行符( ASCII 碼 10)或連續(xù)讀取字符個數(shù)大于 76(在此文件編輯器中,每行最多為 76 個字符)。當(dāng)列單鏈表形 成后,它的首地址將被保存至行單鏈表的相應(yīng)節(jié)點的數(shù)據(jù)域中, 如此動作,直至文件指針指向文件尾部而結(jié)束。 注意:由于本程序中每行以回車符( ASCII 碼為 13)結(jié)束,而當(dāng) 用 Windows 的記事本創(chuàng)建一個文
13、本文件, 打開此文件并用 fgetc() 函數(shù)讀取時,程序?qū)懭肓袉捂湵砉?jié)點中的值是 ASCII 碼為 13 的 回車符。2)保存文件 保存文件操作主要完成將單鏈表中的數(shù)據(jù)寫入文件中的任務(wù), 它 的具體實現(xiàn)流程如下。( 1) 用戶輸入一個保存此單鏈表數(shù)據(jù)的文件名。( 2) 以只寫方式打開此文件,若成功打開此文件,則執(zhí)行步驟(3);否則退出。( 3) 讀取行單鏈表中的節(jié)點數(shù)據(jù)域的值,若值不為空,則執(zhí)行 步驟( 4);否則執(zhí)行步驟( 6)。( 4) 依次讀取行單鏈表節(jié)點中保存的首地址的相應(yīng)列單鏈表 節(jié)點的數(shù)據(jù)域的值,若其值為回車符,則用換行符替代后 將其寫入文件中;否則直接將其值寫入文件中,直至該列
14、 單鏈表中指針域為NULL的最后一個元素結(jié)束。(5) 讀取行單鏈表中的下一個節(jié)點,并跳至步驟(3)。( 6) 關(guān)閉文件,退出。3文件編輯模塊 在文件編輯模塊中, 主要完成以添加或插入的方式輸入字符、 刪 除光標(biāo)所在的當(dāng)前位置或前一個位置的單個字符、朝上下左右 4 個方向的光標(biāo)的移動操作。 下面介紹這 4 個功能的具體設(shè)計與實 現(xiàn)。1)添加字符 當(dāng)光標(biāo)處在文本編輯的最后一行的位置且光標(biāo)后面沒有字符時, 若此時輸入字符, 程序會判斷一行中字符的個數(shù), 若字符個數(shù)不 等于 76,則在當(dāng)前的列單鏈表的最后一個節(jié)點中保存輸入的字 符,然后添加一個新的節(jié)點來保存下一個輸入的字符:若等于 76,則在當(dāng)前的列
15、單鏈表的最后一個節(jié)點中保存輸入的字符,然后在行單鏈表中添加一個新節(jié)點用來保存下一行的列單鏈表的 首地址,添加一個新的列單鏈表節(jié)點來保存下一個用戶輸入的字符。2) 插入字符若光標(biāo)所在處已經(jīng)存在字符, 當(dāng)用戶在當(dāng)前位置輸入字符時, 程 序會調(diào)用 insert() 函數(shù)將輸入的字符在光標(biāo)所在的位置處在列 單鏈表中插入,插入完成后,會調(diào)用 test() 函數(shù)來檢查各行是 否滿足只有 76 個字符的條件,若不滿足此條件,則在此函數(shù)中 會對多出的字符進(jìn)行處理。 下面分別對列單鏈表中字符的插入過 程和單鏈表的檢查過程進(jìn)行介紹。若在第m行,第n列的位置插入一個字符,其insert()過程描 述如下:(1) 定
16、位至行單鏈表中的第 m個節(jié)點,得到這個節(jié)點的數(shù)據(jù)域 的值,其值為對應(yīng)列單鏈表中第一個節(jié)點的地址。(2) 定位至列單鏈表中的第 n-1 個節(jié)點。( 3) 創(chuàng)建一個新的列單鏈表節(jié)點,用其數(shù)據(jù)域保存輸入的字符。(4) 若字符插入在第m行第1列,則直接將行單鏈表中第 m個 節(jié)點的數(shù)據(jù)域的值改變?yōu)樾碌牧袉捂湵砉?jié)點的地址,新的 列單鏈表節(jié)點的指針域指向列單鏈表中原來的第 1 個節(jié)點。 若字符不是插入在第 m 行第 1 列,則執(zhí)行簡單的單鏈表中 插入節(jié)點的操作。(5) 插入此字符后,調(diào)用test()函數(shù),從第m行開始檢查各行 是否滿足每行只允許有 76個字符的條件, 若不滿足此條件,則必須進(jìn)行處理。其 te
17、st() 檢查處理過程描述如下:( 1) 用指針 tail 指向已經(jīng)插入了新節(jié)點的列單鏈表中的最后 一個節(jié)點。(2) 若此單鏈表中節(jié)點數(shù)超過 76個,則指針 p1 會指向此列單 鏈表中的第76個節(jié)點,指針p2指向第77個節(jié)點,并將pl 所指節(jié)點的指針域設(shè)置為 NULL。(3)若 tail 所指節(jié)點的數(shù)據(jù)域為 Enter 鍵( ASCII 為 13)且 在行單鏈表中只有 m個節(jié)點,則在此行單鏈表中添加一個新的節(jié)點,新節(jié)點的數(shù)據(jù)域為 p2的值,指針域為空,并將 m 節(jié)點的指針域指向它 ; 若 tail 所指節(jié)點反而數(shù)據(jù)域為 Enter鍵(ASCII為13)且在行單鏈表中有多于 m個節(jié)點,與 上面不
18、同的是,它執(zhí)行的是在行單鏈表插入一個新的節(jié)點 的操作。(4)若 tail 所指節(jié)點的數(shù)據(jù)域不是回車符, p1 的數(shù)據(jù)域為回車符并且行單鏈表中只有 m個節(jié)點,則在行單鏈表中添加 一個新的節(jié)點,新節(jié)點的數(shù)據(jù)域為 p2 的值,指針域為空, 并將第m節(jié)點的指針域指向它;若tail所指節(jié)點的數(shù)據(jù)域 不為回車符并且行單鏈表中有多于m節(jié)點,則將tail的指針域指向行單鏈表中第 m+1 個節(jié)點所指的列單鏈表的首節(jié)點,并將行單鏈表中第 m+1個節(jié)點的數(shù)據(jù)域修改成指針 p2 的值,并對行單鏈表中第 m+1 個節(jié)點所指的列單鏈表進(jìn)行test() 檢查,相似的處理過程至行單鏈表中的最后一個節(jié) 點結(jié)束。3)刪除字符當(dāng)用
19、戶按下 Del 鍵時,系統(tǒng)會調(diào)用 del() 函數(shù)在單鏈表中刪除當(dāng) 前光標(biāo)所在處的字符; 當(dāng)用戶按下 BackSpace 鍵時,系統(tǒng)也會調(diào) 用這個函數(shù)在單鏈表中刪除當(dāng)前光標(biāo)所在處前一個位置的字符。若在第m行、第n列的位置刪除一個字符,其在列單鏈表中刪除 一個節(jié)點的操作域插入工作十分相似, 所以這里重點介紹刪除該 字符后,單鏈表中數(shù)據(jù)的前移工作過程。(1)在相應(yīng)的列單鏈表中刪除第 n 個節(jié)點。(2)判斷第m行是否存在并且判斷在此行中是否有字符,若第m行不存在,或此行中沒有字符,則結(jié)束字符刪除過程,否 則執(zhí)行步驟( 3)。(3)用tail保存第m行相應(yīng)列單鏈表中最后一個節(jié)點的地址,并將最后一個節(jié)點
20、的指針域保存為第m+1行中相應(yīng)列單鏈表的第一個元素的地址。(4) 計算出第m行中沒有字符的位置的個數(shù) num然后在第m+1 行的相應(yīng)列單鏈表中截取 num個節(jié)點,并將行單鏈表中的第m+1節(jié)點的數(shù)據(jù)域改為相應(yīng)列單鏈表中的第num個節(jié)點后的節(jié)點的地址。(5)調(diào)用m+語句,是變量 m增1,跳至步驟(3),開始對下 一行進(jìn)行處理。4) 移動光標(biāo)移動光標(biāo)的操作主要利用 gotoxy() 函數(shù)來實現(xiàn),過程非常簡單, 只需對當(dāng)前的光標(biāo)位置和移動方向進(jìn)行判斷后,即可執(zhí)行g(shù)otoxy()過程。例如,如果當(dāng)前光標(biāo)在第m行第1列,且按下了光標(biāo)左移鍵,只需將光標(biāo)移至第 m-1 行,第 76 列。4. 剪貼板操作模塊在
21、剪切板操作模塊中, 主要完成對已選定文本的剪切、 復(fù)制和粘 貼工作, 因此剪貼板操作與文本選定工作密切相關(guān)。 下面分別介 紹文本的選定和對選定文本的剪切、復(fù)制和粘貼操作的具體實 現(xiàn)。1 ) 選定文本用戶可按 Ctrl+ 來選定文本,就具體實現(xiàn)而言,兩 者基本相同。 在介紹選定文本的實現(xiàn)過程之前, 先簡要介紹一個 全局的結(jié)構(gòu)數(shù)組 r ,它的元素的類型為 record 結(jié)構(gòu)體類型, 每一個元素可保存一個字符的 x 坐標(biāo)、 y 坐標(biāo)和字符值。其文本 選定的實現(xiàn)過程如下:(1) 當(dāng)用戶按下 Ctrl+ 鍵時,程序?qū)?dāng)前光標(biāo)位 置向左或向右移動一個位置。(2) 當(dāng)前光標(biāo)所在位置的字符的x 坐標(biāo)、 y 坐
22、標(biāo)和字符值保存 在數(shù)組元素 rvalue 中 value 從 0 開始,若按減為 Ctrl+,value 值在原來基礎(chǔ)上每次減 1.(3) 調(diào)用 Colorview() 函數(shù),用不同的顏色來顯示已經(jīng)選定的 當(dāng)前文本,以達(dá)到突出選定文本的效果。2)剪切 用戶可按 Ctrl+X 鍵或通過 Edit 菜單選項來剪切選定的文本, 若 之前沒有選定的文本,此按鍵無效。它的實現(xiàn)過程如下: (1)若全局變量 value 的值大于 0(大于 0 表示已經(jīng)有文本選 定),則執(zhí)行下面操作。(7)( 2)保存當(dāng)前位置的坐標(biāo),利用循環(huán)語句,依次利用x0 至xvalue-1 數(shù)組元素保存已選定字符的坐標(biāo),調(diào)用 del
23、()函數(shù) 在單鏈表中一次刪除一個選定的字符。(3)利用全局變量 backup 保存 value 的值后, 將 value 賦值為 0。( 4)重新在文本編輯器中顯示單鏈表中保存的所有字符,并將 光標(biāo)置位到原來的位置。3)復(fù)制用戶可按 Ctrl+C 鍵或通過 Edit 菜單選項來復(fù)制選定的文本, 復(fù) 制操作的實現(xiàn)比剪切操作簡單,它的實現(xiàn)過程如下:( 1) 保存當(dāng)前位置的坐標(biāo)。( 2) 利用全局變量 backup 保存 value 的值后,將 value 賦值 為 0。( 3) 重新在文本編輯器中顯示單鏈表中保存的所有字符,并將 光標(biāo)置位到原來的位置。4)粘貼用戶可按 Ctrl+V 鍵或通過 Ed
24、it 菜單選項, 完成粘貼操作。 這一 操作必須在剪切或復(fù)制操作之后出現(xiàn)。它的具體實現(xiàn)過程如下:(1) 若全局變量 backup 的值大于 0(大于 0 表示已經(jīng)有字符放 入了剪貼板數(shù)組)中,則執(zhí)行下面的操作。( 2) 保存當(dāng)前位置的坐標(biāo),利用循環(huán)語句,依次利用x0 至xbackup-1 數(shù)組元素保存已選定字符的坐標(biāo)和字符值, 調(diào) 用 insert ()函數(shù)在單鏈表中一次插入一個字符。( 3) 重新在文本編輯器中顯示單鏈表中保存的所有字符,并將 光標(biāo)置位到原來的位置。5菜單控制模塊 在菜單控制模塊中, 主要完成菜單的顯示、 光帶條在子菜單之間 的上下移動或菜單之間的左右移動以及子菜單項的選項工
25、作。 下 面分別介紹這 3 項功能的具體實現(xiàn)。1)顯示菜單用戶可按F1、F2和F3功能鍵來分別調(diào)用 File、Edit和Help菜 單,即完成菜單的顯示。 當(dāng)按下這 3 個功能鍵中的某個功能鍵時, 程序會調(diào)用 menuctrl ()函數(shù)來完成菜單的調(diào)用操作。在 menuctrl ()函數(shù)中,會根據(jù)功能鍵的鍵值調(diào)用drawmen(u value ,flag )函數(shù),參數(shù) value 、 flag 都為局部變量,分別用來保存調(diào) 用某個菜單、某個菜單下的第幾個菜單選項。例如,按 F1 鍵后, 它的默認(rèn)值為 drawmenu(0,0 ),表示繪制 File 菜單及其 5 個菜單選項, 并將菜單選擇光帶
26、條置于第一個菜單選項上。下面簡要描述一下 draw(value , flag )函數(shù)的過程。(1)先取value除以3的余數(shù)m (因為有3個菜單項,所以除 數(shù)選擇3),根據(jù)m的值來繪制不同的菜單。m的取值為0、1、2、。當(dāng)m等于0時,表示繪制File菜單;其余類推。( 2) 然后繪制菜單的邊框及菜單選項值。(3) 取File除以x的余數(shù)t,x的取值視m的取值而定,如當(dāng) m=5時,x=5,因為File 菜單下有5個選項。( 4) 根據(jù) t 的值,用不同的前景色和背景色在原來的位置重新 顯示菜單選項,以達(dá)到光帶條的效果。2) 移動菜單光帶條當(dāng)用戶按F1、F2和F3中的某個功能鍵調(diào)用了某個菜單后,可
27、繼續(xù)按光標(biāo)左移、 右移、 上移和下移鍵來實現(xiàn)菜單之間的切換和菜 單選項之間的切換。( 1 ) 若為左移鍵,則調(diào)用 drawmenu( -value , flag )函數(shù), 將切換至某個菜單的左邊鄰居菜單。若當(dāng)前菜單為最左邊 的 File 菜單,則切換至最右邊的 Help 菜單。若為右移鍵, 則調(diào)用 drawmenu( +value , flag )函數(shù)。( 2) 若為上移鍵,則調(diào)用 drawmenu( value , -flag )函數(shù); 若為下移鍵,則調(diào)用 drawmenu( value , +flag )函數(shù)。3) 選取菜單 當(dāng)用戶將光帶選擇條置于某個菜單選項上時, 可按 Enter 鍵來
28、選取該菜單選項。選取菜單操作的實現(xiàn)比較簡單,它主要利用 a= ( value%3)*10+flag%b 來計算出選擇的菜單選項的編號。選取 不同菜單選項后, a 的值不同。這樣,程序可根據(jù) a 的值,返回 給main ()函數(shù)不同的標(biāo)記,在 main ()函數(shù)中,可根據(jù)標(biāo)記 的不同來執(zhí)行相關(guān)功能。6幫助及其他模塊 幫助模塊主要用于提示用戶如何使用本軟件,它的實現(xiàn)非常簡 單。同樣, 文本的快速預(yù)覽模塊是在原來主窗口顯示模塊的基礎(chǔ) 上,去除了菜單的顯示。主窗口主要由菜單欄、 文本編輯區(qū)和狀態(tài)欄 3 大部分構(gòu)成。 菜單 欄用來顯示菜單項,文本編輯區(qū)主要用來完成文本字符的輸入、 刪除等操作, 狀態(tài)欄主
29、要用來顯示當(dāng)前光標(biāo)在文本窗口中的坐標(biāo) 值。它主要利用文本窗口的 gotoxy ()函數(shù)和 cprintf ()函數(shù) 來實現(xiàn),這里需要對文本窗口的坐標(biāo)進(jìn)行仔細(xì)設(shè)計。.3.2 數(shù)據(jù)結(jié)構(gòu)設(shè)計本程序定義了 3 個結(jié)構(gòu)體, 分別與剪貼板、 列單鏈表和行單鏈表 相關(guān)。下面分別介紹這 3 個結(jié)構(gòu)體及幾個全局變量。1 與剪貼板相關(guān)的 record 結(jié)構(gòu)體typedefstructrecordcharch;intcol,line;record 結(jié)構(gòu)體表示一個字符所具有的屬性,當(dāng)用戶使用相關(guān)按 鍵選定文本后, 選定的文本保存在 record 結(jié)構(gòu)體類型的數(shù)組中。 結(jié)構(gòu)體中各字段表示的意義如下。charch :保存
30、一個選定的文本字符。intcol ,line :分別保存選定字符所在位置的 x 軸坐標(biāo)和 y 軸坐 標(biāo)。2 與列單鏈表相關(guān)的 node 結(jié)構(gòu)體typedefstructnodecharch;structnode*next;node;node 結(jié)構(gòu)體定義了在一個單鏈表中保存行中的單個字符的結(jié)構(gòu), 我們稱由 node 類型的節(jié)點構(gòu)成的單鏈表為列單鏈表。結(jié)構(gòu)體中 各字段表示的意義如下。charch :數(shù)據(jù)域,保存一個字符。structnode*next :指針域,指向列單鏈表中的下一個節(jié)點。3.與行單鏈表相關(guān)的Hnode結(jié)構(gòu)體typedefstructHnodenode*next;structHno
31、de*next1;record;Hnode結(jié)構(gòu)體定義了在一個單鏈表中保存列單鏈表首節(jié)點地址的 結(jié)構(gòu),我們稱由Hnode類型的節(jié)點構(gòu)成的單鏈表為行單鏈表。結(jié)構(gòu)體中各字段表示的意義如下。node*next :數(shù)據(jù)域,。指向列單鏈表的首節(jié)點的地址 structHnode*next1 :指針域,指向列單鏈表中的下一個節(jié)點。4 全局變量及數(shù)組intvalue , backup, NUM:value 保存有值數(shù)組元素的最大下標(biāo)值,backup保存value的副本,NUM保存當(dāng)前行中用戶輸入的字 符個數(shù)。recordr500 :定義一個有 500 個元素的結(jié)構(gòu)體數(shù)組, 每個數(shù)組 元素可保存一個選定的文本字符
32、及其坐標(biāo)值。.3.3 函數(shù)功能描述1) drawmain()函數(shù)原型: voiddrawmain()drawmain() 函數(shù)用于在程序中會只包括菜單欄, 編輯區(qū)和狀態(tài)欄 在內(nèi)的主窗口。2) qview()函數(shù)原型: voidqview(Hnode*q)qview() 函數(shù)用于快速預(yù)覽文本。 q 為指向行單鏈表中第一個節(jié) 點的指針。3) view()函數(shù)原型: viodview(Hnode*q)view() 函數(shù)用于按行顯示保存在單鏈表中的文本字符, q 為指向行單鏈表中第一個節(jié)點的指針4) check()函數(shù)原型: intcheck(Hnode*Hhead,intm,intn)函數(shù)用于在單鏈
33、表中檢查第m行,第n列位置的字符,若為常規(guī)字符,則返回該字符;否則返回 0 或-1.5) judge()函數(shù)原型: intjudje(Hnode*Hhead,intm)judge()函數(shù)用于返回第 m行中不包括回車符在內(nèi)的常規(guī)字符的 個數(shù)。6) del()函數(shù)原型: intdel(Hnode*Hhead,intm,intn)del()函數(shù)用于在單鏈表中刪除第m行,第n列位置的字符。7) test()函數(shù)原型: inttest(Hnode*Hhead,intn) test() 函數(shù)用于執(zhí)行后, 檢驗第 n 行及后面的數(shù)據(jù), 使其滿足每 行不多于 76 個字符的規(guī)則。8) insert()函數(shù)原型
34、: viodinsert(Hnode*Hheadintm,intn,chara)insert()函數(shù)用于在第m行,第n列位置的前一個位置插入單個 字符。9) control()函數(shù)原型: voidcontrol(intA,Hnode*Hhead)control() 函數(shù)用于對左移鍵(右移鍵)進(jìn)行響應(yīng), A 為按鍵的 整數(shù)值,Hhead為行單鏈表的首地址。10) colorview()函數(shù)原型: voicolorview(Hnode*Hhead,intx,inty)colorview() 函數(shù)用于用不同的前、背景色現(xiàn)實選擇的字符。11) drawmenu()函數(shù)原型: voiddrawmenu(
35、intm,intn)drawmenu函數(shù)用于畫菜單,m表示第幾項菜單,n表示第m項的 第 n 個子菜單項。12) menuctrl()函數(shù)原型: intmenuctrl(Hnode*Hhead,intA)menuctrl() 函數(shù)用于菜單控制。13) save()函數(shù)原型: voidsave(Hnode*head)save() 函數(shù)用于將 head 所指的行單鏈表中所指的各個列單鏈表中的數(shù)據(jù)域的值寫入文件,文件路徑和文件名由用戶指定。14) saveas()函數(shù)原型: voidsaveas(Hnode*head)saveas() 函數(shù)用于實現(xiàn)文件另存工作, 文件路徑和文件名由用戶 指定。15)
36、 ope ns()函數(shù)原型: voidopens(Hnode*Hp)opens() 函數(shù)用于從任意文本文件中讀取文件內(nèi)容,保存至行單 鏈表形式的數(shù)據(jù)結(jié)構(gòu)中。)main() 函數(shù)原型: voidmain()main() 函數(shù)為程序的主控函數(shù),對它的描述可參見 .3.1 小節(jié)。.4 程序?qū)崿F(xiàn).4.1 源碼分析1. 程序預(yù)處理程序預(yù)處理包括頭文件的加載, 以及結(jié)構(gòu)體, 常量和全局變量的 定義。/* 文本編輯器 editor 源代碼 */#include#include#include #include#defineLEFT0x4b00/* :光標(biāo)左移 */#defineRIGHT0x4d00/*光標(biāo)
37、右移 */#defineDOWN0x5000/* J 鍵:光標(biāo)下移 */#defineUP0x4800/* T鍵:光標(biāo)上移 */ #defineESC0x011b/*ESC 鍵:取消菜單打開操作 */ #defineENTER0x1c0d/* 回車鍵:換行 */ #defineDEL21248/*DEL 鍵:刪除當(dāng)前字符 */#defineBACK3592/*BackSpace 鍵:刪除當(dāng)前光標(biāo)位置前一個字 符*/#defineCL29440/*ctrl+J鍵:從右至左,選定文本*/#defineCR29696/*ctrl+f鍵:從左到右,選定文本*/#defineCc11779/*ctrl+
38、c鍵:將選定文本,復(fù)制一份到剪貼板中*/#defineCv12054/*ctrl+v鍵:將剪貼板中的內(nèi)容復(fù)制到當(dāng)前位置*/#defineCx11544/*ctrl+x鍵:對選定文本,執(zhí)行剪切操作 */#defineF115104/*F1 鍵:打開文件菜單 */#defineF215360/*F2 鍵:打開編輯菜單 */#defineF3156/*F3 鍵:打開幫助菜單 */ #defineF1017408/*F10 鍵: 進(jìn)入文本快速預(yù)覽模式 */ intvalue,backup,NUM;/*value 保存有值數(shù)組元素的最大下標(biāo)值, backup 保存 value 的 副本,NUM保存當(dāng)前行
39、中的用戶輸入的字符個數(shù)*/typedefstructrecordcharch;/* 保存一字符 */intcol,line;/*x 軸和 y 軸坐標(biāo) */record;recordr500;/* 定義一個有 500 個元素的結(jié)構(gòu)體數(shù)組,保存選 定的文本字符的屬性 */ typedefstructnode/* 定義保存行中的單個字符的結(jié)構(gòu) */ charch;/* 數(shù)據(jù)域:保存一字符 */ structnode*next;/* 指針域:指向下一個結(jié)點的指針 */ node;/* 由此類型節(jié)點構(gòu)成的單鏈表,命名為:列單鏈表 */ typedefstructHnode/* 定義保存所有列單鏈表首節(jié)點
40、的指針的 結(jié)構(gòu) */node*next;/* 指向列單鏈表的首節(jié)點的地址 */ structHnode*nextl;/* 指向下一個節(jié)點的指針 */ Hnode;/* 由此類型節(jié)點構(gòu)成的單鏈表,命名為:行單鏈表 */2. 繪制主窗口繪制文本編輯器主窗口由 drawmain() 函數(shù)來完成,通過準(zhǔn)確定 位相關(guān)輸出對象的坐標(biāo)來完成主窗口的繪制。 主窗口共分為 3 個 區(qū)域:菜單區(qū),文本編輯去和狀態(tài)欄區(qū)。voiddrawmain()/* 畫主窗口函數(shù) */inti,j;gotoxy(1,1);/* 在文本窗口中設(shè)置光標(biāo)至 (1,1) 處*/ textbackground(7);/* 選擇新的文本背景
41、顏色 ,7 為 LIGHTGRAY 淡灰色 */textcolor(O);/*在文本模式中選擇新的字符顏色0為BLACK黑在文本窗口的 (1,1) 位置處中插入一個空行 */x,y) 中 x 不變, y+*/在窗口左邊輸出 -, 即畫出主窗口的左邊在窗口右邊,輸出 - ,即畫出主窗口的右在第 2行,第 2列開始 */ 在窗口頂端,輸出 -*/ 在第 25 行,第 2 列開始 */ 在窗口底端,輸出 -*/在窗口左上角,輸出 -*/在窗口左下角,輸出 -*/在窗口右上角,輸出 -*/*/insline();/*for(i=1;i=24;i+)gotoxy(1,1+i);/*cprintf(%c,
42、196);/*界*/gotoxy(80,1+i);cprintf(%c,196);/*邊界*/for(i=1;i=79;i+)gotoxy(1+i,2);/*cprintf(%c,196);/*gotoxy(1+i,25);/*cprintf(%c,196);/*gotoxy(1,1);cprintf(%c,196);/* gotoxy(1,24);cprintf(%c,196);/* gotoxy(80,1);cprintf(%c,196);/*gotoxy(80,24);cprintf(%c,196);/* 在窗口右下角,輸出 -*/gotoxy(7,1);cprintf(%c%cFile
43、%c%c,179,17,179);/*|*/gotoxy(27,1);cprintf(%c%cEdit%c%c,179,17,179);/*|*/gotoxy(47,1);cprintf(%c%cHelp%c%c,179,17,179);/*|*/gotoxy(5,25);/* 跳至窗口底端 */textcolor(1);cprintf(Row:1Col:1);gotoxy(68,25);cprintf(Version2.0);3. 文本字符顯示輸出 文本字符顯示輸出模塊的作用是通過循環(huán)讀取各單鏈表, 醬爆錯 在單鏈表眾多的字符在文本編輯區(qū)中顯示輸出。( 1) 通過 qview(hnode*q
44、) 函數(shù),可實現(xiàn)文本字符的快速預(yù)覽。( 2) 通過 view(honde*q) 函數(shù),可實現(xiàn)文本字符在編輯區(qū)域的 顯示。voidqview(Hnode*q)/* 快速預(yù)覽文本:開頭: #,回車: */voidview(Hnode*q);/*view() 函數(shù)聲明 */node*p;inti;window(1,1,80,25);/* 定義文本窗口大小 */clrscr();/* 清屏 */* 循環(huán)讀取兩個單鏈表中的值: q 是一個指向行單鏈表首節(jié)點的 指針,此單鏈表數(shù)據(jù)域的值為實際保存各行字符的列單鏈表 p 中的首 節(jié)點地址 */dop=q-next;/*p 指向保存行數(shù)據(jù)的列單鏈表的首節(jié)點的地
45、址 */ cprintf(#);/* 每行開頭,打印此字符,不管前面是否有回車 符*/while(p!=NULL)/* 循環(huán)讀取單鏈表 p 中的值 */if(p-ch=13)putch(*);/* 若為回車鍵,打印出 * 號*/ elseputch(p-ch);/* 輸出各行中的字符到預(yù)覽窗口 */p=p-next;/* 指向下一個節(jié)點 */q=q-nextl;/* 指向下一個節(jié)點 */printf(n);/* 輸出一個回車 */ while(q!=NULL);getch();clrscr();drawmain();/* 按任意鍵后,回到主窗口界面 */ window(2,2,79,23);t
46、extbackground(9); for(i=0;inext;while(p!=NULL&p-ch=32&p-chch!=13&p-ch!= -1)/* 指針 p 不能為空,且數(shù)據(jù)域必須為常規(guī)字符 */putch(p-ch);/* 在文本窗口中輸出該字符 */p=p-next;/* 指向下一個節(jié)點 */q=q-nextl;/* 指向下一個節(jié)點 */ if(p-ch=13|p-ch=-1)&q!=NULL)gotoxy(1,wherey()+1);/*若ch為回車或EOF標(biāo)記,光標(biāo)跳至下行的開始處*/while(q!=NULL);/*逐行逐列顯示文本字符*/4. 刪除字符程序調(diào)用 del(Ho
47、nde*Hhead,intm,intn) 函數(shù)來完成刪除第行、 第列位置的字符。 它的具體過程在功能模塊設(shè)計部分已經(jīng)詳細(xì)介 紹。下面介紹另外兩個對字符進(jìn)行檢測的函數(shù), 它在字符的刪除、 插入等許多操作中都有用到。(1) 調(diào)用 check(Hnode*Head,intm,intn) 函數(shù),在單鏈表中檢查第m行、第n列位置的字符,若為常規(guī)字符,則返回該 字符;否則返回 0 或-1. ,(2) 調(diào)用 judge(Hnode*Hhead,intm) 函數(shù),在單鏈表中統(tǒng)計第m行中的常規(guī)字符的總個數(shù),并返回統(tǒng)計值。intdel(Hnode*Hhead,intm,intn)/*del():刪除第 m行,第
48、n 列位置的字符 */Hnode*q,*q1;node*p1,*p2,*tail; inti,num=0,j,flag=0;q=Hhead;if(n=0&m=1)return;/* 第 1 行,第 0 列不存在 */ if(n=0&m1)/* 若為第 0 列字符,但行必須大于 1,執(zhí)行向上行 移處理 */n=76;m=m-1;gotoxy(n,m);/* 移至第 m-1 行,第 76 列 */ flag=1;/* 移位的標(biāo)志置 1*/for(i=1;inextl;p1=q-next;for(i=1;inext;p2=p1-next;/*p2 指向列單鏈表中的第 n 個元素 */if(n=1)/
49、* 若是刪除第m行第1列的字符*/ q-next=p1-next;free(p1);elsep1-next=p2-next;/*在單鏈表中刪除第 m行第n列的元素*/free(p2);/*刪除掉第m行第n列的元素后,處理行單鏈表中第 m個節(jié)點后 的數(shù)據(jù)向前移的任務(wù) */while(num=judge(Hhead,m+)0)/* 執(zhí)行一次 judge(Head,m) 后,m才加1.這里必須滿足行常規(guī)字符數(shù)不為0的條件*/p1=q-next;q1=q;if(p1!=NULL)/* 若當(dāng)前行非空 */ while(p1-next!=NULL)p1=p1-next;tail=p1;/*tail 保存列
50、單鏈表最后一個元素的地址 */ q=q-nextl;/* 指向下一行的元素的地址 */p1=p2=q-next;tail-next=p1;/*tail的指針域指向下一行的第一個元素的地址*/else/* 若當(dāng)前行的字符個數(shù)為 0, 即刪除該字符后,只剩下回車符,則將下一個行單鏈表中節(jié)點的數(shù)據(jù)域移至前一下節(jié)點的數(shù)據(jù) 域*/q=q-nextl;p1=p2=q-next;q1-next=p1;/*q1-next 指向下一行的第一個元素的地址 */ for(i=0;inext;if(p2-ch=13)break;/* 若為回車,跳出循環(huán) */ q-next=p2;/* 在列單鏈表中去掉移至上行的元素
51、*/ p1-next=NULL;/* 下行移至上行的最后一個元素,指針置空 */ returnflag;/* 返回 0:表示沒有換位,返回 1:表示有換位 */ intcheck(Hnode*Hhead,intm,intn)/*check(): 在單鏈表中檢查 第 m 行第 n 列位置的字符,若為常規(guī)字符,則返回該字符 */inti;Hnode*q;node*p;q=Hhead;for(i=1;inextl;p=q-next;/*獲取第m個節(jié)點的數(shù)據(jù)域*/for(i=1;inext;if(p-ch=13)return-1;/* 若第m行,第n列的字符為回車鍵, 則返回 -1*/if(p-ch=
52、32&p-chch;/*若第 m行,第 n 列的字符為常規(guī)字符 , 則返回該字符 */elsereturnO;/* 若第m行,第n列的字符既非回車符又非常規(guī)字 符,則返回 0*/intjudge(Hnode*Hhead,intm)/*judge():返回第 m 行中的常規(guī)字符總的個數(shù),不包括回車符 */Hnode*q;node*p;inti,num=0;q=Hhead;for(i=1;inextl;if(q=NULL)return-1;/* 返回-1,表示第 m行不存在 */ p=q-next;while(p-next!=NULL)p=p-next;num+;/*統(tǒng)計第m行的字符個數(shù)*/* 行
53、尾字符還沒有判斷,接下來判斷行尾字符 */if(p-ch=13&num=0)return0;/* 返回 0, 表示當(dāng)前行只有一個 回車字符 */if(p-ch=32&p-chch=13&num!=O)returnnum;/*返回 num,表示當(dāng)前行的最后一個字符為回車符,不計算在內(nèi) */elsereturn1;/* 返回num,表示當(dāng)前行中只有一個字符,且沒有 回車符 */5. 插入字符在文本編輯區(qū)中插入字符的工作由 insert(Hnode,*Hhead,intm,intn,chara) 函 數(shù) 和 test(Hnode*Hhead,intn) 函數(shù)配合完成。( 1) 通過 insert(Hnode*Hhead,intm,intn,chara) 函數(shù),在第m行、第n列的位置之前的一個位置,在單鏈表中插入字符a。(2) 通過 test(Hnode*hhead,intn) 函數(shù),檢查和處理第 n 行及后 面 的 數(shù) 據(jù) , 使 其 滿 足 每 行 不 超 過
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 大連東軟信息學(xué)院《工程材料》2023-2024學(xué)年第二學(xué)期期末試卷
- 重慶市涪陵區(qū)涪陵高中2025屆高三下學(xué)期階段性測試(三)物理試題試卷含解析
- 福建省德化一中、安溪一中2025屆高三下學(xué)期第一次摸底考試歷史試題理試卷含解析
- 民辦四川天一學(xué)院《古代漢語下》2023-2024學(xué)年第一學(xué)期期末試卷
- 白喉、百日咳、破傷風(fēng)、乙肝四聯(lián)制劑項目風(fēng)險分析和評估報告
- 貴州體育職業(yè)學(xué)院《專項理論與實踐Ⅵ》2023-2024學(xué)年第二學(xué)期期末試卷
- 鐵路貨運(yùn)站服務(wù)項目風(fēng)險分析和評估報告
- 安徽省皖南地區(qū)2024-2025學(xué)年高三考前最后一次模擬試題語文試題試卷含解析
- 新疆理工學(xué)院《TeamProject》2023-2024學(xué)年第一學(xué)期期末試卷
- 濟(jì)寧醫(yī)學(xué)院《文獻(xiàn)檢索與研究綜述》2023-2024學(xué)年第二學(xué)期期末試卷
- 贛價協(xié)〔2023〕9號江西省建設(shè)工程造價咨詢服務(wù)收費(fèi)基準(zhǔn)價
- DBJ53T-19-2007加芯攪拌樁技術(shù)規(guī)程
- 職稱評定打分細(xì)則(學(xué)院排名用)
- 檢驗員基礎(chǔ)知識培訓(xùn).ppt
- 心理治療師復(fù)習(xí)
- 液壓常用元件符號
- 第十一章 地役權(quán)
- 重慶某高速公路合同段分離式隧道實施性施工組織設(shè)計(低瓦斯隧道)
- 風(fēng)機(jī)基礎(chǔ)土方開挖專項施工方案
- 藥店聘書樣板
- 虛偽的人yy頻道設(shè)計 第三者圖案模版頻道設(shè)計
評論
0/150
提交評論