版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領
文檔簡介
1、<p><b> 文本編輯器</b></p><p> 文本編輯器是最常用的文檔創(chuàng)建和編輯工具。隨著計算機科學與技術(shù)的發(fā)展,用來處理文本的編輯器隨處可見,并且形式多樣。比如,Windows下的記事本,寫字板,EditPlus,UltraEdit等都是十分優(yōu)秀的文本編輯器和處理工具。在本章中,我們將向讀者講解如何利用C語言來發(fā)展開發(fā)一個簡易的文本編輯器。</p>&
2、lt;p> 1 設計目的</p><p> 利用C語言的單鏈表數(shù)據(jù)結(jié)構(gòu)及相關(guān)函數(shù),本章編程實現(xiàn)了一個與DOS操作系統(tǒng)下的Edit相似的文本編輯器。再次文本編輯器中,用戶可以通過快捷和選擇菜單項,完成基本的文本編輯器和文件處理工作。</p><p> 通過文章的介紹,讀者可以了解文本編輯器的開發(fā)過程,掌握菜單的開發(fā)技巧,加深對文件操作的理解。更重要的是,希望此程序能拋磚引
3、玉,引領讀者掌握編程的方法和技巧,開發(fā)出更優(yōu)秀的程序。</p><p> 2 功能描述 </p><p> 如圖.1所示,文本編輯器主要由五大功能模塊構(gòu)成,它們分別是文件操作模塊,文本編輯模塊,剪切操作模塊,菜單控制模塊和幫助及其他模塊。下面分別簡要介紹功能模塊的功能。</p><p> 文件操作模塊。在文件操作模塊中,主要完成文件的創(chuàng)建,打開,保存和
4、另存操作。用戶可以選擇File菜單上的New子菜單來完成新建文本文件操作;選擇File菜單上的Save子菜單來完成保存文件操作選擇File菜單上的Open子菜單來完成打開文件操作;選擇Flie菜單上的Save as子菜單來完成文件的另存為操作。在文件的打開,保存和另存為操作中,系統(tǒng)會提示用戶輸入文件路徑及文件名。值得一提的是,當用戶打開一個文件時,指定的文件必須存在,否則系統(tǒng)會報錯。</p><p> 文本編輯
5、器模塊。在文本編輯器模塊中,主要完成在編輯窗口中以添加或插入的方式輸入字符,刪除光標所在當前位置的單個字符或前一個位置的單個字符,朝上下左右4個方向的光標移動操作。當光標所在位置及后面的位置沒有字符時,系統(tǒng)會以添加的方式輸入字符;當光標所在位置及后面的位置有字符時,系統(tǒng)會已插入的方式輸入字符。用戶可以使用BackSpace鍵刪除光標前一個字符,也可以使用Del鍵刪除當前位置的字符或刪除Ctrl+左移(右移)鍵i選定了的多個字符。用戶可以
6、使用左移鍵(←),右移鍵(→),上移鍵(↑)和下移鍵(↓)來移動光標位置。</p><p> 剪貼板操作模塊。在剪貼板操作模塊中,主要完成對已選定文本的剪切,復制,粘貼工作。如果用戶要剪切文本以便可以將它移動到其他位置,可通過Ctrl+X左移鍵(右移鍵)先選定文本,然后選擇Edit菜單上的Cut子菜單或按Ctrl+X快捷鍵來完成剪切任務。如果用戶要復制文本以便可以將它黏貼到其他位置,必須先選定文本,然后選擇Ed
7、it菜單上的Copy紫菜單或按Ctrl+C快捷鍵來完成復制任務。如果用戶要粘貼剪切或復制的文本,必須將光標置于要粘貼文本的位置,然后選擇Edit菜單上的Paste子菜單或按Ctrl+V快捷鍵來完成粘貼任務。</p><p> 菜單控制模塊。在菜單控制模塊中,主要完成菜單的顯示。光帶條在子菜單之間的上下移動或菜單之間的左右移動和子菜單項的選取。本文本編輯器共有Flie,Edit和Help3個子菜單項,用戶可以分別
8、按F1,F2和F3功能鍵來完成這3個菜單項的調(diào)用,即顯示某項菜單。用戶可按光標上移或下移鍵在某菜單項的子菜單之間循環(huán)移動,也可使用光標的左移或右移鍵在3個菜單項之間循環(huán)移動。當光帶移動到某個字菜單項上時,用戶此時可使用Enter鍵來選取相關(guān)菜單選項。 </p><p> 幫助及其他模塊。在幫助及其他模塊中,主要完成系統(tǒng)功能及按鍵的簡要介紹。其他模塊包括文本的快速預覽和窗口的顯示。用戶可按F10功能鍵來打開快速預
9、覽窗口,在快速預覽窗口中沒有功能菜單條。主窗口要有菜單欄,文本編輯區(qū)和狀態(tài)欄三大部分構(gòu)成,菜單欄用來顯示菜單項,文本編輯區(qū)主要用來文本字符的輸入,刪除等操作,狀態(tài)欄主要用來顯示當前光標在文本窗口中的坐標值。</p><p> 注意:Turbo C2.默認定義的文本窗口為整個屏幕,共有80列(或40列),25行的文本單元,每個單元包括一個字符和一個屬性,字符即ASCII碼字符,屬性規(guī)定該字符的顏色和強度。同時,他
10、還規(guī)定整個屏幕的左上角坐標為(1,1),右下角坐標為(80,25)。并規(guī)定沿水平方向為X軸,方向朝右;眼垂直方向為Y軸,方向朝下。</p><p> 3 總體設計</p><p> 3.1 功能模塊設計</p><p> 在.2節(jié)中,簡單描述了各功能模塊的作用,下面分別介紹各功能模塊的具體設計。在介紹各功能模塊的具體設計之前,有必要先描述一下
11、主程序的執(zhí)行流程。</p><p><b> 程序執(zhí)行主流程</b></p><p> 文本編輯器程序執(zhí)行主流程如圖.2所示,它是在main()函數(shù)中實現(xiàn)的。他首先初始化一些全局變量及結(jié)構(gòu)數(shù)組,接著調(diào)用drawmain()函數(shù)來顯示主窗口,然后調(diào)用while(1)進入主循環(huán),等待用戶按鍵,最后程序根據(jù)用戶的按鍵值,進行相應的處理,完成文本編輯的相關(guān)工作。下面對圖.
12、2中的按鍵判斷和相關(guān)處理作補充說明。</p><p> 若按鍵為常規(guī)字符,即其ASCII碼大于32小于127,則繼續(xù)判斷在文本編輯區(qū)的當前光標位置有沒有字符,若有字符,則調(diào)用insert()函數(shù),將此字符插入在當前位置,否則在判斷沒有滿行后,將此字符添加在單鏈表的數(shù)據(jù)域中,若此行已滿,則執(zhí)行添加新行操作。</p><p> 若按鍵為Enter鍵,則將光標移至下一行的行首,等待用戶輸入新
13、的字符。</p><p> 若按鍵為光標移動鍵(左,右,上,下)且移動后的位置滿足相關(guān)條件,則執(zhí)行g(shù)otoxy()操作,將光標移動至目標位置。</p><p> 若按鍵為BackSpace鍵,則將調(diào)用Del()函數(shù)將光標的前一個字符從單鏈表中刪除;若按鍵為Del鍵,也將調(diào)用del()函數(shù)將光標的當前位置的字符從單鏈表中刪除。</p><p> 若按鍵為Ctrl
14、開頭的按鍵,則執(zhí)行與其相關(guān)的操作。具體來說,若為Ctrl+左移鍵(←),則將選定當前光標的位置開始向右的一個字符,若按住Ctrl鍵不放,連續(xù)按右移鍵,可以選定多個字符。若為Ctrl+左移鍵(←),則將執(zhí)行與以上相同的操作。若為Ctrl+X鍵,則將選定相關(guān)內(nèi)容保存起來,且從單鏈表中刪除選定的字符后重新顯示單鏈表的內(nèi)容。若為Ctrl+C鍵,則將選定的相關(guān)內(nèi)容保存起來,重新顯示單鏈表中的內(nèi)容(目的:為了去除字符的底色)。若為Ctrl+V鍵,則
15、調(diào)用insert()函數(shù)將保存起來的字符插入在單鏈表中,并重新顯示單鏈表中的內(nèi)容。</p><p> 若按鍵為F10鍵,則調(diào)用qview()函數(shù),實現(xiàn)文本的快速預覽。</p><p> 若按鍵為F1,F2,F3功能鍵,則調(diào)用menuctrl()菜單控制函數(shù),在此函數(shù)中完成案件的具體判斷和執(zhí)行相應功能操作。若為F1鍵,則調(diào)用File菜單;若為F2鍵,則調(diào)用Edit菜單;若為F3鍵,則調(diào)用
16、Help菜單。</p><p><b> 2.文件操作模塊</b></p><p> 在此模塊中,主要實現(xiàn)文件的新建、打開、保存和另存為操作。在此系統(tǒng)中,文件的新建操作實現(xiàn)比較簡單,文件另存為操作與保存操作類似,下面重點介紹在此文本編輯器程序中,文件的打開和保存操作的具體設計和實現(xiàn)。在介紹之前,我們先簡單描述一下程序中用到的保存數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。在此程序中,共有兩種
17、類型的單鏈表,我們稱其為行單鏈表和列單鏈表,一個列單鏈表用來保存一行的字符,有多少行即有多少個這樣的單鏈表。行單鏈表只有一個,它的每個節(jié)點的數(shù)據(jù)域用來保存不同列單鏈表的首節(jié)點的地址。例如,第4行第4列的字符保存在行單鏈表的第4個節(jié)點的數(shù)據(jù)域所指的列單鏈表的第4個節(jié)點的數(shù)據(jù)域中。有關(guān)具體數(shù)據(jù)結(jié)構(gòu)的定義,在后面的小節(jié)中會有具體介紹。</p><p><b> 1)打開文件</b></p&
18、gt;<p> 文件的打開流程如圖.3所示,它首先提示用戶輸入要打開文件的文件名,若該文件不存在或由于其他原因打開失敗,則會結(jié)束文件打開操作。若文件成功打開并且文件指針沒有到文件尾,則從文件中一次讀取一個字符,并將該字符添加到一列單鏈表節(jié)點中,直至遇到換行符(ASCII碼10)或連續(xù)讀取字符個數(shù)大于76(在此文件編輯器中,每行最多為76個字符)。當列單鏈表形成后,它的首地址將被保存至行單鏈表的相應節(jié)點的數(shù)據(jù)域中,如此動作
19、,直至文件指針指向文件尾部而結(jié)束。</p><p> 注意:由于本程序中每行以回車符(ASCII碼為13)結(jié)束,而當用Windows的記事本創(chuàng)建一個文本文件,打開此文件并用fgetc()函數(shù)讀取時,程序?qū)懭肓袉捂湵砉?jié)點中的值是ASCII碼為13的回車符。</p><p><b> 2)保存文件</b></p><p> 保存文件操作主要完
20、成將單鏈表中的數(shù)據(jù)寫入文件中的任務,它的具體實現(xiàn)流程如下。</p><p> 用戶輸入一個保存此單鏈表數(shù)據(jù)的文件名。</p><p> 以只寫方式打開此文件,若成功打開此文件,則執(zhí)行步驟(3);否則退出。</p><p> 讀取行單鏈表中的節(jié)點數(shù)據(jù)域的值,若值不為空,則執(zhí)行步驟(4);否則執(zhí)行步驟(6)。</p><p> 依次讀取行
21、單鏈表節(jié)點中保存的首地址的相應列單鏈表節(jié)點的數(shù)據(jù)域的值,若其值為回車符,則用換行符替代后將其寫入文件中;否則直接將其值寫入文件中,直至該列單鏈表中指針域為NULL的最后一個元素結(jié)束。</p><p> 讀取行單鏈表中的下一個節(jié)點,并跳至步驟(3)。</p><p><b> 關(guān)閉文件,退出。</b></p><p><b> 3
22、.文件編輯模塊</b></p><p> 在文件編輯模塊中,主要完成以添加或插入的方式輸入字符、刪除光標所在的當前位置或前一個位置的單個字符、朝上下左右4個方向的光標的移動操作。下面介紹這4個功能的具體設計與實現(xiàn)。</p><p><b> 添加字符</b></p><p> 當光標處在文本編輯的最后一行的位置且光標后面沒有字
23、符時,若此時輸入字符,程序會判斷一行中字符的個數(shù),若字符個數(shù)不等于76,則在當前的列單鏈表的最后一個節(jié)點中保存輸入的字符,然后添加一個新的節(jié)點來保存下一個輸入的字符:若等于76,則在當前的列單鏈表的最后一個節(jié)點中保存輸入的字符,然后在行單鏈表中添加一個新節(jié)點用來保存下一行的列單鏈表的首地址,添加一個新的列單鏈表節(jié)點來保存下一個用戶輸入的字符。</p><p><b> 插入字符</b>&l
24、t;/p><p> 若光標所在處已經(jīng)存在字符,當用戶在當前位置輸入字符時,程序會調(diào)用insert()函數(shù)將輸入的字符在光標所在的位置處在列單鏈表中插入,插入完成后,會調(diào)用test()函數(shù)來檢查各行是否滿足只有76個字符的條件,若不滿足此條件,則在此函數(shù)中會對多出的字符進行處理。下面分別對列單鏈表中字符的插入過程和單鏈表的檢查過程進行介紹。</p><p> 若在第m行,第n列的位置插入一個
25、字符,其insert()過程描述如下:</p><p> 定位至行單鏈表中的第m個節(jié)點,得到這個節(jié)點的數(shù)據(jù)域的值,其值為對應列單鏈表中第一個節(jié)點的地址。</p><p> 定位至列單鏈表中的第n-1個節(jié)點。</p><p> 創(chuàng)建一個新的列單鏈表節(jié)點,用其數(shù)據(jù)域保存輸入的字符。</p><p> 若字符插入在第m行第1列,則直接將行單
26、鏈表中第m個節(jié)點的數(shù)據(jù)域的值改變?yōu)樾碌牧袉捂湵砉?jié)點的地址,新的列單鏈表節(jié)點的指針域指向列單鏈表中原來的第1個節(jié)點。若字符不是插入在第m行第1列,則執(zhí)行簡單的單鏈表中插入節(jié)點的操作。</p><p> 插入此字符后,調(diào)用test()函數(shù),從第m行開始檢查各行是否滿足每行只允許有76個字符的條件,若不滿足此條件,則必須進行處理。</p><p> 其test()檢查處理過程描述如下:<
27、;/p><p> 用指針tail指向已經(jīng)插入了新節(jié)點的列單鏈表中的最后一個節(jié)點。</p><p> 若此單鏈表中節(jié)點數(shù)超過76個,則指針p1會指向此列單鏈表中的第76個節(jié)點,指針p2指向第77個節(jié)點,并將p1所指節(jié)點的指針域設置為NULL。</p><p> 若tail所指節(jié)點的數(shù)據(jù)域為Enter鍵(ASCII為13)且在行單鏈表中只有m個節(jié)點,則在此行單鏈表中添
28、加一個新的節(jié)點,新節(jié)點的數(shù)據(jù)域為p2的值,指針域為空,并將m節(jié)點的指針域指向它;若tail所指節(jié)點反而數(shù)據(jù)域為Enter鍵(ASCII為13)且在行單鏈表中有多于m個節(jié)點,與上面不同的是,它執(zhí)行的是在行單鏈表插入一個新的節(jié)點的操作。</p><p> 若tail所指節(jié)點的數(shù)據(jù)域不是回車符,p1的數(shù)據(jù)域為回車符并且行單鏈表中只有m個節(jié)點,則在行單鏈表中添加一個新的節(jié)點,新節(jié)點的數(shù)據(jù)域為p2的值,指針域為空,并將第
29、m節(jié)點的指針域指向它;若tail所指節(jié)點的數(shù)據(jù)域不為回車符并且行單鏈表中有多于m節(jié)點,則將tail的指針域指向行單鏈表中第m+1個節(jié)點所指的列單鏈表的首節(jié)點,并將行單鏈表中第m+1個節(jié)點的數(shù)據(jù)域修改成指針p2的值,并對行單鏈表中第m+1個節(jié)點所指的列單鏈表進行test()檢查,相似的處理過程至行單鏈表中的最后一個節(jié)點結(jié)束。</p><p><b> 刪除字符</b></p>
30、<p> 當用戶按下Del鍵時,系統(tǒng)會調(diào)用del()函數(shù)在單鏈表中刪除當前光標所在處的字符;當用戶按下BackSpace鍵時,系統(tǒng)也會調(diào)用這個函數(shù)在單鏈表中刪除當前光標所在處前一個位置的字符。</p><p> 若在第m行、第n列的位置刪除一個字符,其在列單鏈表中刪除一個節(jié)點的操作域插入工作十分相似,所以這里重點介紹刪除該字符后,單鏈表中數(shù)據(jù)的前移工作過程。</p><p>
31、 在相應的列單鏈表中刪除第n個節(jié)點。</p><p> 判斷第m行是否存在并且判斷在此行中是否有字符,若第m行不存在,或此行中沒有字符,則結(jié)束字符刪除過程,否則執(zhí)行步驟(3)。</p><p> 用tail保存第m行相應列單鏈表中最后一個節(jié)點的地址,并將最后一個節(jié)點的指針域保存為第m+1行中相應列單鏈表的第一個元素的地址。</p><p> 計算出第m行中沒
32、有字符的位置的個數(shù)num,然后在第m+1行的相應列單鏈表中截取num個節(jié)點,并將行單鏈表中的第m+1節(jié)點的數(shù)據(jù)域改為相應列單鏈表中的第num個節(jié)點后的節(jié)點的地址。</p><p> 調(diào)用m++語句,是變量m增1,跳至步驟(3),開始對下一行進行處理。</p><p><b> 移動光標</b></p><p> 移動光標的操作主要利用go
33、toxy()函數(shù)來實現(xiàn),過程非常簡單,只需對當前的光標位置和移動方向進行判斷后,即可執(zhí)行g(shù)otoxy()過程。例如,如果當前光標在第m行第1列,且按下了光標左移鍵,只需將光標移至第m-1行,第76列。</p><p><b> 4.剪貼板操作模塊</b></p><p> 在剪切板操作模塊中,主要完成對已選定文本的剪切、復制和粘貼工作,因此剪貼板操作與文本選定工作
34、密切相關(guān)。下面分別介紹文本的選定和對選定文本的剪切、復制和粘貼操作的具體實現(xiàn)。</p><p><b> 選定文本</b></p><p> 用戶可按Ctrl+<-或Ctrl+->來選定文本,就具體實現(xiàn)而言,兩者基本相同。在介紹選定文本的實現(xiàn)過程之前,先簡要介紹一個全局的結(jié)構(gòu)數(shù)組r[],它的元素的類型為record結(jié)構(gòu)體類型,每一個元素可保存一個字符的
35、x坐標、y坐標和字符值。其文本選定的實現(xiàn)過程如下:</p><p> 當用戶按下Ctrl+<-或Ctrl+->鍵時,程序?qū)斍肮鈽宋恢孟蜃蠡蛳蛴乙苿右粋€位置。</p><p> 當前光標所在位置的字符的x坐標、y坐標和字符值保存在數(shù)組元素r[value]中value從0開始,若按減為Ctrl+<-,value值在原來基礎上每次加1;若按鍵為Ctrl+->,val
36、ue值在原來基礎上每次減1.</p><p> 調(diào)用Colorview()函數(shù),用不同的顏色來顯示已經(jīng)選定的當前文本,以達到突出選定文本的效果。</p><p><b> 剪切</b></p><p> 用戶可按Ctrl+X鍵或通過Edit菜單選項來剪切選定的文本,若之前沒有選定的文本,此按鍵無效。它的實現(xiàn)過程如下:</p>
37、<p> ?。?)若全局變量value的值大于0(大于0表示已經(jīng)有文本選定),則執(zhí)行下面操作。</p><p> ?。?)保存當前位置的坐標,利用循環(huán)語句,依次利用x[0]至x[value-1]數(shù)組元素保存已選定字符的坐標,調(diào)用del()函數(shù)在單鏈表中一次刪除一個選定的字符。</p><p> ?。?)利用全局變量backup保存value的值后,將value賦值為0。<
38、/p><p> ?。?)重新在文本編輯器中顯示單鏈表中保存的所有字符,并將光標置位到原來的位置。</p><p><b> 3)復制</b></p><p> 用戶可按Ctrl+C鍵或通過Edit菜單選項來復制選定的文本,復制操作的實現(xiàn)比剪切操作簡單,它的實現(xiàn)過程如下:</p><p> 保存當前位置的坐標。</
39、p><p> 利用全局變量backup保存value的值后,將value賦值為0。</p><p> 重新在文本編輯器中顯示單鏈表中保存的所有字符,并將光標置位到原來的位置。</p><p><b> 4)粘貼</b></p><p> 用戶可按Ctrl+V鍵或通過Edit菜單選項,完成粘貼操作。這一操作必須在剪切或
40、復制操作之后出現(xiàn)。它的具體實現(xiàn)過程如下:</p><p> 若全局變量backup的值大于0(大于0表示已經(jīng)有字符放入了剪貼板數(shù)組)中,則執(zhí)行下面的操作。</p><p> 保存當前位置的坐標,利用循環(huán)語句,依次利用x[0]至x[backup-1]數(shù)組元素保存已選定字符的坐標和字符值,調(diào)用insert()函數(shù)在單鏈表中一次插入一個字符。</p><p> 重新
41、在文本編輯器中顯示單鏈表中保存的所有字符,并將光標置位到原來的位置。</p><p><b> 5.菜單控制模塊</b></p><p> 在菜單控制模塊中,主要完成菜單的顯示、光帶條在子菜單之間的上下移動或菜單之間的左右移動以及子菜單項的選項工作。下面分別介紹這3項功能的具體實現(xiàn)。</p><p><b> 顯示菜單</
42、b></p><p> 用戶可按F1、F2和F3功能鍵來分別調(diào)用File、Edit和Help菜單,即完成菜單的顯示。當按下這3個功能鍵中的某個功能鍵時,程序會調(diào)用menuctrl()函數(shù)來完成菜單的調(diào)用操作。在menuctrl()函數(shù)中,會根據(jù)功能鍵的鍵值調(diào)用drawmenu(value,flag)函數(shù),參數(shù)value、flag都為局部變量,分別用來保存調(diào)用某個菜單、某個菜單下的第幾個菜單選項。例如,按F
43、1鍵后,它的默認值為drawmenu(0,0),表示繪制File菜單及其5個菜單選項,并將菜單選擇光帶條置于第一個菜單選項上。下面簡要描述一下draw(value,flag)函數(shù)的過程。</p><p> 先取value除以3的余數(shù)m(因為有3個菜單項,所以除數(shù)選擇3),根據(jù)m的值來繪制不同的菜單。m的取值為0、1、2、。當m等于0時,表示繪制File菜單;其余類推。</p><p>
44、 然后繪制菜單的邊框及菜單選項值。</p><p> 取File除以x的余數(shù)t,x的取值視m的取值而定,如當m=5時,x=5,因為File菜單下有5個選項。</p><p> 根據(jù)t的值,用不同的前景色和背景色在原來的位置重新顯示菜單選項,以達到光帶條的效果。</p><p><b> 移動菜單光帶條</b></p><
45、;p> 當用戶按F1、F2和F3中的某個功能鍵調(diào)用了某個菜單后,可繼續(xù)按光標左移、右移、上移和下移鍵來實現(xiàn)菜單之間的切換和菜單選項之間的切換。</p><p> 若為左移鍵,則調(diào)用drawmenu(--value,flag)函數(shù),將切換至某個菜單的左邊鄰居菜單。若當前菜單為最左邊的File菜單,則切換至最右邊的Help菜單。若為右移鍵,則調(diào)用drawmenu(++value,flag)函數(shù)。</p
46、><p> 若為上移鍵,則調(diào)用drawmenu(value,--flag)函數(shù);若為下移鍵,則調(diào)用drawmenu(value,++flag)函數(shù)。</p><p><b> 選取菜單</b></p><p> 當用戶將光帶選擇條置于某個菜單選項上時,可按Enter鍵來選取該菜單選項。選取菜單操作的實現(xiàn)比較簡單,它主要利用a=(value%3
47、)*10+flag%b來計算出選擇的菜單選項的編號。選取不同菜單選項后,a的值不同。這樣,程序可根據(jù)a的值,返回給main()函數(shù)不同的標記,在main()函數(shù)中,可根據(jù)標記的不同來執(zhí)行相關(guān)功能。</p><p><b> 6.幫助及其他模塊</b></p><p> 幫助模塊主要用于提示用戶如何使用本軟件,它的實現(xiàn)非常簡單。同樣,文本的快速預覽模塊是在原來主窗口
48、顯示模塊的基礎上,去除了菜單的顯示。</p><p> 主窗口主要由菜單欄、文本編輯區(qū)和狀態(tài)欄3大部分構(gòu)成。菜單欄用來顯示菜單項,文本編輯區(qū)主要用來完成文本字符的輸入、刪除等操作,狀態(tài)欄主要用來顯示當前光標在文本窗口中的坐標值。它主要利用文本窗口的gotoxy()函數(shù)和cprintf()函數(shù)來實現(xiàn),這里需要對文本窗口的坐標進行仔細設計。</p><p> .3.2數(shù)據(jù)結(jié)構(gòu)設計</
49、p><p> 本程序定義了3個結(jié)構(gòu)體,分別與剪貼板、列單鏈表和行單鏈表相關(guān)。下面分別介紹這3個結(jié)構(gòu)體及幾個全局變量。</p><p> 與剪貼板相關(guān)的record結(jié)構(gòu)體</p><p> typedef struct record</p><p><b> {</b></p><p><
50、b> char ch;</b></p><p> int col,line;</p><p><b> }record;</b></p><p> record結(jié)構(gòu)體表示一個字符所具有的屬性,當用戶使用相關(guān)按鍵選定文本后,選定的文本保存在record結(jié)構(gòu)體類型的數(shù)組中。結(jié)構(gòu)體中各字段表示的意義如下。</p>
51、<p> char ch:保存一個選定的文本字符。</p><p> int col,line:分別保存選定字符所在位置的x軸坐標和y軸坐標。</p><p> 與列單鏈表相關(guān)的node結(jié)構(gòu)體</p><p> typedef struct node</p><p><b> {</b></
52、p><p><b> char ch;</b></p><p> struct node *next;</p><p><b> }node;</b></p><p> node結(jié)構(gòu)體定義了在一個單鏈表中保存行中的單個字符的結(jié)構(gòu),我們稱由node類型的節(jié)點構(gòu)成的單鏈表為列單鏈表。結(jié)構(gòu)體中各字段表
53、示的意義如下。</p><p> char ch:數(shù)據(jù)域,保存一個字符。</p><p> struct node*next:指針域,指向列單鏈表中的下一個節(jié)點。</p><p> 與行單鏈表相關(guān)的Hnode結(jié)構(gòu)體</p><p> typedef struct Hnode</p><p><b>
54、 {</b></p><p> node *next;</p><p> struct Hnode *next1;</p><p><b> }record;</b></p><p> Hnode結(jié)構(gòu)體定義了在一個單鏈表中保存列單鏈表首節(jié)點地址的結(jié)構(gòu),我們稱由Hnode類型的節(jié)點構(gòu)成的單鏈表為行單鏈表
55、。結(jié)構(gòu)體中各字段表示的意義如下。</p><p> node *next:數(shù)據(jù)域,。指向列單鏈表的首節(jié)點的地址</p><p> struct Hnode*next1:指針域,指向列單鏈表中的下一個節(jié)點。</p><p><b> 全局變量及數(shù)組</b></p><p> int value,backup,NUM
56、:value保存有值數(shù)組元素的最大下標值,backup保存value的副本,NUM保存當前行中用戶輸入的字符個數(shù)。</p><p> record r[500]:定義一個有500個元素的結(jié)構(gòu)體數(shù)組,每個數(shù)組元素可保存一個選定的文本字符及其坐標值。</p><p> .3.3函數(shù)功能描述</p><p> 1)drawmain()</p><
57、p> 函數(shù)原型:void drawmain()</p><p> drawmain()函數(shù)用于在程序中會只包括菜單欄,編輯區(qū)和狀態(tài)欄在內(nèi)的主窗口。</p><p><b> 2)qview()</b></p><p> 函數(shù)原型:void qview(Hnode*q)</p><p> qview()函數(shù)
58、用于快速預覽文本。q為指向行單鏈表中第一個節(jié)點的指針。</p><p><b> 3)view()</b></p><p> 函數(shù)原型:viod view(Hnode*q)</p><p> view()函數(shù)用于按行顯示保存在單鏈表中的文本字符,q為指向行單鏈表中第一個節(jié)點的指針。</p><p><b>
59、; 4)check()</b></p><p> 函數(shù)原型:int check(Hnode*Hhead,int m,int n)</p><p> 函數(shù)用于在單鏈表中檢查第m行,第n列位置的字符,若為常規(guī)字符,則返回該字符;否則返回0或-1.</p><p><b> 5)judge()</b></p><
60、;p> 函數(shù)原型:int judje(Hnode*Hhead,int m)</p><p> judge()函數(shù)用于返回第m行中不包括回車符在內(nèi)的常規(guī)字符的個數(shù)。</p><p><b> 6)del()</b></p><p> 函數(shù)原型:int del(Hnode*Hhead,int m,int n)</p>&
61、lt;p> del()函數(shù)用于在單鏈表中刪除第m行,第n列位置的字符。</p><p><b> 7)test()</b></p><p> 函數(shù)原型:int test(Hnode*Hhead,int n)</p><p> test()函數(shù)用于執(zhí)行后,檢驗第n行及后面的數(shù)據(jù),使其滿足每行不多于76個字符的規(guī)則。</p>
62、;<p> 8)insert()</p><p> 函數(shù)原型:viod insert(Hnode*Hheadint m,int n,char a)</p><p> insert()函數(shù)用于在第m行,第n列位置的前一個位置插入單個字符。</p><p> 9)control()</p><p> 函數(shù)原型:void c
63、ontrol(int A,Hnode*Hhead)</p><p> control()函數(shù)用于對左移鍵(右移鍵)進行響應,A為按鍵的整數(shù)值,Hhead為行單鏈表的首地址。</p><p> 10)colorview()</p><p> 函數(shù)原型:voi colorview(Hnode*Hhead,int x,int y)</p><p&
64、gt; colorview()函數(shù)用于用不同的前、背景色現(xiàn)實選擇的字符。</p><p> 11)drawmenu()</p><p> 函數(shù)原型:void drawmenu(int m,int n)</p><p> drawmenu函數(shù)用于畫菜單,m表示第幾項菜單,n表示第m項的第n個子菜單項。</p><p> 12)menu
65、ctrl()</p><p> 函數(shù)原型:int menuctrl(Hnode*Hhead,int A)</p><p> menuctrl()函數(shù)用于菜單控制。</p><p><b> 13)save()</b></p><p> 函數(shù)原型:void save(Hnode*head)</p>&
66、lt;p> save()函數(shù)用于將head所指的行單鏈表中所指的各個列單鏈表中的數(shù)據(jù)域的值寫入文件,文件路徑和文件名由用戶指定。</p><p> 14)saveas()</p><p> 函數(shù)原型:void saveas(Hnode*head)</p><p> saveas()函數(shù)用于實現(xiàn)文件另存工作,文件路徑和文件名由用戶指定。</p>
67、;<p> 15)opens()</p><p> 函數(shù)原型:void opens(Hnode*Hp)</p><p> opens()函數(shù)用于從任意文本文件中讀取文件內(nèi)容,保存至行單鏈表形式的數(shù)據(jù)結(jié)構(gòu)中。</p><p><b> )main()</b></p><p> 函數(shù)原型:void m
68、ain()</p><p> main()函數(shù)為程序的主控函數(shù),對它的描述可參見.3.1小節(jié)。</p><p><b> .4程序?qū)崿F(xiàn)</b></p><p><b> .4.1 源碼分析</b></p><p><b> 1.程序預處理</b></p>
69、<p> 程序預處理包括頭文件的加載,以及結(jié)構(gòu)體,常量和全局變量的定義。</p><p> /*文本編輯器editor源代碼*/</p><p> #include <stdio.h></p><p> #include <conio.h></p><p> #include <bios.h&
70、gt;</p><p> #include <math.h></p><p> #define LEFT 0x4b00 /*←:光標左移*/</p><p> #define RIGHT 0x4d00 /*→:光標右移*/</p><p> #define DOWN 0x5000 /*↓鍵:光標下移*/</
71、p><p> #define UP 0x4800 /*↑鍵:光標上移*/</p><p> #define ESC 0x011b /*ESC鍵:取消菜單打開操作*/</p><p> #define ENTER 0x1c0d /*回車鍵:換行*/</p><p> #define DEL 21248 /*DEL鍵:
72、刪除當前字符*/</p><p> #define BACK 3592 /*BackSpace鍵:刪除當前光標位置前一個字符*/</p><p> #define CL 29440 /*ctrl+←鍵:從右至左,選定文本*/</p><p> #define CR 29696 /*ctrl+→鍵:從左到右,選定文本*/</p&
73、gt;<p> #define Cc 11779 /*ctrl+c鍵:將選定文本,復制一份到剪貼板中*/</p><p> #define Cv 12054 /*ctrl+v鍵:將剪貼板中的內(nèi)容復制到當前位置*/</p><p> #define Cx 11544 /*ctrl+x鍵:對選定文本,執(zhí)行剪切操作*/</p>&l
74、t;p> #define F1 15104 /*F1鍵:打開文件菜單*/</p><p> #define F2 15360 /*F2鍵:打開編輯菜單*/</p><p> #define F3 156 /*F3鍵:打開幫助菜單*/</p><p> #define F10 17408 /*F10鍵:進入文本快速預
75、覽模式*/</p><p> int value,backup,NUM;</p><p> /*value保存有值數(shù)組元素的最大下標值,backup保存value的副本,NUM保存當前行中的用戶輸入的字符個數(shù)*/</p><p> typedef struct record</p><p><b> {</b>&
76、lt;/p><p> char ch; /*保存一字符*/</p><p> int col, line; /*x軸和y軸坐標*/</p><p><b> }record;</b></p><p> record r[500]; /*定義一個有500個元素的結(jié)構(gòu)體數(shù)組,保存選定的文本字符的屬性*/</p&
77、gt;<p> typedef struct node /*定義保存行中的單個字符的結(jié)構(gòu)*/</p><p><b> {</b></p><p> char ch; /*數(shù)據(jù)域:保存一字符*/</p><p> struct node *next; /*指針域:指向下一個結(jié)點的指針*/</p><p&
78、gt; }node;/*由此類型節(jié)點構(gòu)成的單鏈表,命名為:列單鏈表*/</p><p> typedef struct Hnode /*定義保存所有列單鏈表首節(jié)點的指針的結(jié)構(gòu)*/</p><p><b> {</b></p><p> node *next; /*指向列單鏈表的首節(jié)點的地址*/</p><p>
79、 struct Hnode *nextl; /*指向下一個節(jié)點的指針*/</p><p> }Hnode;/*由此類型節(jié)點構(gòu)成的單鏈表,命名為:行單鏈表*/</p><p><b> 2.繪制主窗口</b></p><p> 繪制文本編輯器主窗口由drawmain()函數(shù)來完成,通過準確定位相關(guān)輸出對象的坐標來完成主窗口的繪制。主窗口共分
80、為3個區(qū)域:菜單區(qū),文本編輯去和狀態(tài)欄區(qū)。</p><p> void drawmain() /*畫主窗口函數(shù)*/</p><p><b> {</b></p><p><b> int i,j;</b></p><p> gotoxy(1,1); /*在文本窗口中設置光標至(1
81、,1)處*/</p><p> textbackground(7); /*選擇新的文本背景顏色,7為LIGHTGRAY淡灰色*/</p><p> textcolor(0); /*在文本模式中選擇新的字符顏色0為BLACK黑*/</p><p> insline(); /*在文本窗口的(1,1)位置處中插入一個空行*/</p&g
82、t;<p> for(i=1;i<=24;i++)</p><p><b> {</b></p><p> gotoxy(1,1+i); /*(x,y)中x不變,y++*/</p><p> cprintf("%c",196); /*在窗口左邊輸出-,即畫出主窗口的左邊界 */</p
83、><p> gotoxy(80,1+i);</p><p> cprintf("%c",196); /*在窗口右邊,輸出-,即畫出主窗口的右邊界*/</p><p><b> }</b></p><p> for(i=1;i<=79;i++)</p><p><
84、b> {</b></p><p> gotoxy(1+i,2); /*在第2行,第2列開始*/</p><p> cprintf("%c",196); /*在窗口頂端,輸出-*/</p><p> gotoxy(1+i,25); /*在第25行,第2列開始*/</p><p> c
85、printf("%c",196); /*在窗口底端,輸出-*/</p><p><b> }</b></p><p> gotoxy(1,1); cprintf("%c",196); /*在窗口左上角,輸出-*/</p><p> gotoxy(1,24); cprintf("%c&
86、quot;,196); /*在窗口左下角,輸出-*/</p><p> gotoxy(80,1); cprintf("%c",196); /*在窗口右上角,輸出-*/</p><p> gotoxy(80,24); cprintf("%c",196); /*在窗口右下角,輸出-*/</p><p> gotoxy(7,
87、1); cprintf("%c %c File %c %c",179,17,,179); /* | < > |*/</p><p> gotoxy(27,1); cprintf("%c %c Edit %c %c",179,17,,179); /* | < > |*/</p><p> gotoxy(47,1);
88、 cprintf("%c %c Help %c %c",179,17,,179); /* | < > |*/</p><p> gotoxy(5,25); /*跳至窗口底端*/</p><p> textcolor(1);</p><p> cprintf(" Row:1 Col:1");
89、</p><p> gotoxy(68,25);</p><p> cprintf("Version 2.0");</p><p><b> }</b></p><p> 3.文本字符顯示輸出</p><p> 文本字符顯示輸出模塊的作用是通過循環(huán)讀取各單鏈表,醬爆錯
90、在單鏈表眾多的字符在文本編輯區(qū)中顯示輸出。</p><p> 通過qview(hnode*q)函數(shù),可實現(xiàn)文本字符的快速預覽。</p><p> 通過view(honde*q)函數(shù),可實現(xiàn)文本字符在編輯區(qū)域的顯示。</p><p> void qview(Hnode *q) /*快速預覽文本:開頭:#,回車:* */</p><p>&
91、lt;b> {</b></p><p> void view(Hnode *q); /*view()函數(shù)聲明*/</p><p><b> node *p;</b></p><p><b> int i;</b></p><p> window(1,1,80,25); /
92、*定義文本窗口大小*/</p><p> clrscr(); /*清屏*/</p><p> /*循環(huán)讀取兩個單鏈表中的值:q是一個指向行單鏈表首節(jié)點的指針,</p><p> 此單鏈表數(shù)據(jù)域的值為實際保存各行字符的列單鏈表p中的首節(jié)點地址*/</p><p><b> do{</b></p>&l
93、t;p> p=q->next; /*p指向保存行數(shù)據(jù)的列單鏈表的首節(jié)點的地址*/</p><p> cprintf("#"); /*每行開頭,打印此字符,不管前面是否有回車符*/</p><p> while(p!=NULL) /*循環(huán)讀取單鏈表p中的值*/</p><p><b> {</b>&l
94、t;/p><p> if(p->ch==13) putch('*'); /*若為回車鍵,打印出*號*/</p><p><b> else</b></p><p> putch(p->ch); /*輸出各行中的字符到預覽窗口*/</p><p> p=p->next; /*指向下
95、一個節(jié)點*/</p><p><b> }</b></p><p> q=q->nextl; /*指向下一個節(jié)點*/</p><p> printf("\n");/*輸出一個回車*/</p><p> }while(q!=NULL);</p><p><b&
96、gt; getch();</b></p><p><b> clrscr();</b></p><p> drawmain();/*按任意鍵后,回到主窗口界面*/</p><p> window(2,2,79,23);</p><p> textbackground(9);</p>&
97、lt;p> for(i=0;i<24;i++)</p><p> insline(); /*插入24個空行*/</p><p> window(3,3,78,23);</p><p> textcolor(10);</p><p><b> }</b></p><p> v
98、oid view(Hnode *q) /*按行顯示保存在單鏈表中的文本字符,q為指向行單鏈表中第一個節(jié)點的指針*/</p><p><b> {</b></p><p> node *p; /*p為保存列單鏈表節(jié)點元素地址的指針*/</p><p> clrscr(); /*清屏*/</p><p> /*雙重
99、循環(huán),讀取并顯示保存在單鏈表中字符*/</p><p><b> do{</b></p><p> p=q->next;</p><p> while(p!=NULL&&p->ch>=32&&p->ch<127&&p->ch!=13&&p-
100、>ch!=-1) /*指針p不能為空,且數(shù)據(jù)域必須為常規(guī)字符*/</p><p><b> {</b></p><p> putch(p->ch);/*在文本窗口中輸出該字符*/</p><p> p=p->next; /*指向下一個節(jié)點*/</p><p><b> }</
101、b></p><p> q=q->nextl; /*指向下一個節(jié)點*/</p><p> if((p->ch==13||p->ch==-1)&&q!=NULL) gotoxy(1,wherey()+1); /*若ch為回車或EOF標記,光標跳至下行的開始處*/</p><p> }while(q!=NULL); /*逐
102、行逐列顯示文本字符*/</p><p><b> }</b></p><p><b> 4.刪除字符</b></p><p> 程序調(diào)用del(Honde*Hhead,int m,int n)函數(shù)來完成刪除第行、第列位置的字符。它的具體過程在功能模塊設計部分已經(jīng)詳細介紹。下面介紹另外兩個對字符進行檢測的函數(shù),它在字符
103、的刪除、插入等許多操作中都有用到。</p><p> 調(diào)用check(Hnode*Head,int m,int n)函數(shù),在單鏈表中檢查第m行、第n列位置的字符,若為常規(guī)字符,則返回該字符;否則返回0或-1., </p><p> 調(diào)用judge(Hnode*Hhead,int m)函數(shù),在單鏈表中統(tǒng)計第m行中的常規(guī)字符的總個數(shù),并返回統(tǒng)計值。</p><p>
104、 int del(Hnode *Hhead,int m,int n) /*del():刪除第m行,第n列位置的字符*/</p><p><b> {</b></p><p> Hnode *q,*q1;</p><p> node *p1,*p2,*tail;</p><p> int i,num=0,j,f
105、lag=0;</p><p><b> q=Hhead;</b></p><p> if(n==0&&m==1) return; /*第1行,第0列不存在*/</p><p> if(n==0&&m>1) /*若為第0列字符,但行必須大于1,執(zhí)行向上行移處理*/</p><p&g
106、t;<b> {</b></p><p><b> n=76;</b></p><p><b> m=m-1;</b></p><p> gotoxy(n,m);/*移至第m-1行,第76列*/</p><p> flag=1; /*移位的標志置1*/</p&g
107、t;<p><b> }</b></p><p> for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/</p><p> q=q->nextl;</p><p> p1=q->next;</p><p> for(i=1;i<n-1;i++) /*定位至
108、列單鏈表中的第n-1個元素*/</p><p> p1=p1->next;</p><p> p2=p1->next; /*p2指向列單鏈表中的第n個元素*/</p><p> if(n==1) /*若是刪除第m行第1列的字符*/</p><p><b> {</b></p><p
109、> q->next=p1->next;</p><p><b> free(p1);</b></p><p><b> }</b></p><p><b> else</b></p><p><b> {</b></p&g
110、t;<p> p1->next=p2->next; /*在單鏈表中刪除第m行第n列的元素*/</p><p><b> free(p2);</b></p><p><b> }</b></p><p> /*刪除掉第m行第n列的元素后,處理行單鏈表中第m個節(jié)點后的數(shù)據(jù)向前移的任務*/<
111、;/p><p> while((num=judge(Hhead,m++))>0) /*執(zhí)行一次judge(Head,m)后,m才加1.這里必須滿足行常規(guī)字符數(shù)不為0的條件*/</p><p><b> {</b></p><p> p1=q->next; q1=q;</p><p> if(p1!=NUL
112、L) /*若當前行非空*/</p><p><b> {</b></p><p> while(p1->next!=NULL)</p><p> p1=p1->next;</p><p> tail=p1;/*tail保存列單鏈表最后一個元素的地址*/</p><p> q=
113、q->nextl; /*指向下一行的元素的地址*/</p><p> p1=p2=q->next;</p><p> tail->next=p1; /*tail的指針域指向下一行的第一個元素的地址*/</p><p><b> }</b></p><p> else /*若當前行的字符個數(shù)為0
114、,即刪除該字符后,只剩下回車符,則將下一個行單鏈表中節(jié)點的數(shù)據(jù)域移至前一下節(jié)點的數(shù)據(jù)域*/</p><p><b> {</b></p><p> q=q->nextl; p1=p2=q->next;</p><p> q1->next=p1;/*q1->next指向下一行的第一個元素的地址*/</p&g
115、t;<p><b> }</b></p><p> for(i=0;i<76-num;i++)</p><p> /*當前行還有76-num個空位沒有字符,在下一行的單鏈表中讀取字符,直至遇到回車符為止*/</p><p><b> {</b></p><p> p1=
116、p2; /*p1指向p2的前一個節(jié)點,p2指向行單鏈表中下一個節(jié)點*/</p><p> p2=p2->next;</p><p> if(p2->ch==13) break; /*若為回車,跳出循環(huán)*/</p><p><b> }</b></p><p> q->next=p2; /*
117、在列單鏈表中去掉移至上行的元素*/</p><p> p1->next=NULL;/*下行移至上行的最后一個元素,指針置空*/</p><p><b> }</b></p><p> return flag; /*返回0:表示沒有換位,返回1:表示有換位*/</p><p><b> }</
118、b></p><p> int check(Hnode *Hhead,int m,int n) /*check():在單鏈表中檢查第m行第n列位置的字符,若為常規(guī)字符,則返回該字符*/</p><p><b> {</b></p><p><b> int i;</b></p><p>
119、<b> Hnode *q;</b></p><p><b> node *p;</b></p><p><b> q=Hhead;</b></p><p> for(i=1;i<m;i++) /*定位至行單鏈表中的第m個元素*/</p><p> q=q-&g
120、t;nextl;</p><p> p=q->next;/*獲取第m個節(jié)點的數(shù)據(jù)域*/</p><p> for(i=1;i<n;i++) /*定位至列單鏈表中的第n個元素*/</p><p> p=p->next;</p><p> if(p->ch==13) return -1; /*若第m行,第n列的字
121、符為回車鍵,則返回-1*/</p><p> if(p->ch>=32&&p->ch<127) return p->ch; /*若第m行,第n列的字符為常規(guī)字符,則返回該字符*/</p><p> else return 0; /*若第m行,第n列的字符既非回車符又非常規(guī)字符,則返回0*/</p><p><
122、b> }</b></p><p> int judge(Hnode *Hhead,int m) /*judge():返回第m行中的常規(guī)字符總的個數(shù),不包括回車符*/</p><p><b> {</b></p><p><b> Hnode *q;</b></p><p>
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- c_文本編輯器課程設計
- 文本編輯器課程設計
- 文本編輯器課程設計報告
- java課程設計--文本編輯器
- java課程設計---文本編輯器
- java課程設計---文本編輯器
- c_編寫的文本編輯器課程設計
- vb課程設計文本編輯器
- java課程設計(文本編輯器)
- c++課程設計--簡單文本編輯器的設計
- vb課程設計報告----文本編輯器
- vb課程設計報告---文本編輯器
- 簡易文本編輯器課程設計報告
- 數(shù)據(jù)結(jié)構(gòu)課程設計--文本編輯器
- 操作系統(tǒng)課程設計---文本編輯器
- 微機原理課程設計—簡易文本編輯器
- 文本編輯器
- visual_basic課程設計報告---文本編輯器
- 數(shù)據(jù)結(jié)構(gòu)課程設計---簡易文本編輯器
- 文本編輯器_java課程設計實驗報告
評論
0/150
提交評論