text
text
text是由文字堆砌而成、可以閱讀的東西。
我們將text打散為基本單位,以便理解text:
書寫的觀點:英文的基本單位叫做letter,即是ABC...這26種英文字母。中文的基本單位叫做字,即是字典裡面那些字。
語言的觀點:英文的基本單位叫做word,由一個以上的letter組成,例如apple、boy、cat。中文的基本單位叫做詞,由一個以上的字組成,例如蘋果、男孩、貓。
電腦的觀點:基本單位叫做character,繁中譯作「字元」,簡中譯作「字符」。電腦可以處理的字元,主要是依據ASCII與Unicode的規定。英文字元有ABCDabcd1234,.!?等。中文字元包括了字典裡面那些字,以及ㄅㄆㄇㄈ。,、:等注音符號與標點符號;絕大部分的中文字都有收錄,只漏了一些冷僻的字。
在電腦螢幕上顯示字元,只要打開文字編輯器,選擇輸入法,用手指敲敲鍵盤即可。還可以進一步,將電腦螢幕上的字元,儲存到純文字檔案裡;將純文字檔案裡的字元,顯示在電腦螢幕上。
想要寫程式在電腦螢幕上顯示字元,只要運用scanf、printf、cin、cout,就會以command-line interface顯示字元。還可以進一步,寫程式將字元儲存到檔案;寫程式從檔案讀取字元。
想要處理字元,相關的學問有字串學與編碼理論。相關的本站文件有string與code。
想要顯示字元,屬於graphics的領域。
font
font就是文字的造型。譯作「字體」或「字型」。
電腦顯示字元,必須透過字型。只要有文字的地方,通常都能更換字型,例如文字編輯器、瀏覽器、作業系統、命令提示字元。可供選擇的字型,主要是看你的電腦安裝了哪些字型。
text editor
text viewer
文字閱讀器。閱讀純文字檔案的工具。
text editor
文字編輯器。閱讀和編輯純文字檔案的工具。
程式設計師開發程式碼的工具軟體IDE,也包含文字編輯器:Microsoft Visual Studio、Code::Blocks、VS Code、Atom。
文字編輯器的函式庫:Scintilla。
Textual User Interface
作業系統提供的文字介面。此處討論於此介面開發文字編輯器。
Windows作業系統的cmd.exe,在MSDN網站上面可以找到詳細的說明文件。
Mac OS作業系統的Terminal.app、Linux作業系統的console,則是用ANSI escape code這套公定標準來控制色彩和游標──這跟BBS所用的是一樣的。也有現成工具:ncurses。
graphical user interface
作業系統提供的圖形介面。此處討論於此介面開發文字編輯器。
利用程式語言C#、Java、Qt,掌握C# Windows Form、Java Swing、Qt Widgets的使用方式,接著建立視窗、視窗重繪、建立捲軸、繪製文字、監聽滑鼠事件、監聽鍵盤事件、……。
程式語言也內建了簡易的文字編輯器,例如C#的TextBox、Java的JTextArea,我們可以直接拿來用。
graphical user interface in browser
瀏覽器提供的圖形介面。此處討論於此介面開發文字編輯器。
利用HTML與JavaScript,掌握HTML DOM與JavaScript Event的概念。
HTML也內建了簡易的文字編輯器,例如<textarea>,我們可以直接拿來用。
file I/O
「讀取硬碟」比「讀取記憶體」花費更多時間。預先將檔案從硬碟複製到記憶體,每當捲動文字編輯器的畫面,不讀取硬碟而是讀取記憶體。
文字檔案不大時,一口氣把整個檔案填入記憶體。
文字檔案很大時,只好動態載入資料:隨著畫面捲動,將對應的檔案填入記憶體。
純文字檔案頂多幾MB,而家用電腦的記憶體都是數GB、行動電話的記憶體也有1GB,記憶體十分充足。大可不必動態載入資料,搞的自己要死不活。
text data structure
文字總是以「行」為單位呈現。遭遇斷行字元,隨即換行顯示。文字切成一行一行分開儲存,是個不錯的策略。
注意到,Windows、Mac OS、Linux的斷行字元都不一樣,必須小心處理。
一行文字的資料結構,主要有四種。
一行頂多幾百個字元,採用array(插入刪除很慢)或者list(定位很慢),簡潔明快。
當一行有成千上萬個字元,採用rope(二元樹)或者unrolled linked list(list串起一堆array),打字不會卡卡的。
串聯每一行的資料結構,同樣是上述四種。
caret
文字編輯器都有一個閃爍的游標,告訴使用者現在編輯到哪裡了。用兩個變數分別記錄第幾行、第幾字元(的左邊)。
敲打上下左右鍵,移動游標。游標只能移動到有字的地方。
scroll
當游標超出畫面範圍,畫面必須配合捲動。同樣地,用兩個變數分別記錄螢幕的左上角是第幾行、第幾字元(的左邊)。
ctrl 方向鍵:改變捲動位置,而不改變游標位置。
select
「選取」可以拆解成這些基本動作:一、紀錄游標位置。二、移動游標。三、文字顏色反白。
shift 方向鍵:選取文字。
shift alt 方向鍵:選取矩形區域。
edit
「編輯」可以拆解成這些基本動作:一、刪除選取文字。二、取消選取。三、根據游標位置,修改文字。四、移動游標。
insert:切換編輯模式,插入、覆蓋。
cut / copy / paste
「剪下、複製、貼上」可以拆解成這些基本動作:一、將標示的文字複製一份到暫存區。二、刪除標示的文字。三、在游標之處插入暫存區裡的文字。
方才提的是在同一個軟體之內複製貼上。如果要在不同軟體之間複製貼上,就必須提升層級,使用作業系統所管轄的暫存區,例如Windows作業系統的剪貼簿。
find / replace
「尋找、取代」可以拆解成這些基本動作:一、搜尋字串。二、選取字串。三、刪除選取字串。四、插入字串。
搜尋字串可以使用string searching演算法、使用regular expression。
undo / redo
「復原、取消復原」。兩種做法:一、建立一個stack,記錄所有變動。二、文字資料結構改成可持久化資料結構RRB-tree,以便融入所有變動,例如immer。
復原非常耗費記憶體,尤其是經常更動大量文字。為了防止記憶體用罄:一、只儲存最近幾步。二、將stack寫入硬碟、存成檔案。
使用Windows Office,總是出現檔案開頭是波浪符號的暫存檔案,那就是將stack寫入硬碟。
text parser
text parser
文字剖析器。讀取文字,剖析語法,建立階層架構,形成一棵語法樹。亦得反向操作,以階層架構生成文字。
text parser經典應用
documentation generator:生成文件。用剖析器擷取程式碼的函數與註解,自動產生說明文件。例如Doxygen。
lightweight markup language:生成文件。例如Markdown生成HTML,例如Wikitext生成維基百科版型。
integrated development environment:編輯程式碼。例如Microsoft Visual Studio。
interactive development environment:生成文件、執行程式碼。例如jupyter。
template engine:生成程式碼。例如EJS生成Javascript。
minification:縮短程式碼、掩飾程式碼。例如Google Closure Compiler壓縮Javascript。
transpiler:轉換程式碼為另一種程式語言。例如emscripten。
如何製作text parser?
請參考parsing。相關的學校課程是編譯器、程式語言理論。相關的本站文章是Formal Language。
autocomplete / autocorrect
自動完成是自動選字填詞的功能,自動校正是自動修正錯別字的功能。搜尋引擎、IDE、網頁表單都有這些功能。
自動完成:使用者編輯的時候,即時從游標位置往前抓取字元,直到遇到空白鍵,形成一段短字串。預先建立單字表格,從中搜尋這段短字串,看看哪些單字的開頭等於這段短字串。在畫面上列出那些單字,供使用者選擇。
自動校正:同上,看看哪個單字最接近這段短字串。最後刪除原字串、插入新字串。
字串相似度,可以使用hamming distance、k-mismatch string searching、k-difference string searching、edit distance。各個演算法的速度和準度都不一樣,讀者可以自行取捨。
UVa 1462
auto line wrap / auto indent / auto highlight
自動排版,讓文字好讀。
自動換行:文字到達畫面邊界,就換行顯示。
自動縮排:自動添減空白鍵、tab鍵、enter鍵。
語法高亮:根據語法結構,自動替文字上色。
rich text editor
rich text與markup language
rich text是指附加了字型、大小、顏色、位置、圖片、超連結等等資訊的text。實務上的做法是:定義特殊的格式,以便附加資訊。著名的rich text格式像是HTML、TEX、RTF。
以HTML為例,它藉由「標籤」來附加資訊。首先使用純文字編輯器讀取.html檔案,編輯rich text,然後使用瀏覽器讀取.html檔案,就變成美美的網頁了。
為了附加資訊,於是發明了保留字的概念:某些文字必須當作「此為附加資訊」的提示,不能當作純文字。
為了讓保留字也可以成為純文字,於是又發明了跳脫字元的概念:以罕見的文字組合,代替保留字。
以HTML為例,標籤不能當作純文字,例如<p>。如果想要顯示跟標籤一模一樣的純文字,就必須利用跳脫字元&:寫下<就變成<,寫下>就變成>,寫下<p>就變成<p>了。
聰明的讀者肯定馬上又想到:如果想要顯示<的純文字呢?答案是跳脫字元本身也要設計跳脫字元:寫下&就變成&,寫下&lt;就變成<。
rich text editor
可以實際動手操作的範例:http://ckeditor.com/demo。
用純文字編輯器來設計rich text,眼睛看著純文字、腦袋想著真實畫面,迂迴反直覺。於是有人提倡WYSIWYG(所見即所得)的概念:編輯器直接顯示真實畫面,使用者直接編輯真實畫面;編輯器根據使用者的操作過程,暗地裡生成rich text。
知名的富文字編輯器軟體,例如編輯RTF的Microsoft Word、編輯HTML的Adobe DreamWeaver。現在網路發達,也有很多人開發網頁版的富文字編輯器,例如CKEditor、TinyMCE。
很多IDE也有富文字編輯器,以便直覺地設計GUI程式,就是俗稱的「拉介面」。例如Microsoft Visual Studio、C++Builder、Qt Creator。
程式語言已經內建了富文字編輯器,例如C#的RichTextBox、Qt的QTextEdit,我們可以直接拿來用。
文字是人類最擅長的媒體,富文字編輯器舉目皆是。即時通訊軟體Skype、LINE,社群網站Facebook,部落格網站Wordpress、Medium,微網誌網站Twitter、微博,都能見到富文字編輯器。
如何製作rich text editor?
我從未設計過富文字編輯器,所以無法介紹。各位可以參與開源專案、從做中學;或者也可以進入相關行業、入門學藝。
想要發明rich text的格式,請參考各種markup language,從既有的格式汲取經驗。
想要繪製真實畫面,請參考各種排版引擎。
UVa 12417
input method
input method
輸入法。用來輸入文字的軟體。
鍵盤最初是美國人發明的,上面只有印製英文字母,也只能輸入英文字母。其他國家為了輸入自己的語言文字,只好在鍵盤上面額外印製符號,然後自己設計輸入法。臺灣的鍵盤額外印上注音符號,配合注音輸入法,就能輸入中文字了。除了作業系統內建的輸入法以外,著名的繁體中文輸入法還有自然輸入法和酷音輸入法。
現在科技發達,輸入文字不見得要透過鍵盤,而是透過觸控螢幕、麥克風,所以輸入法的發展重點也隨著改變。早期的輸入法,著重拆字組字;近代的輸入法,著重選字填詞。事過境遷、滄海桑田,過去那些拆字組字的輸入法,例如倉頡輸入法和嘸蝦米輸入法,現在看來彷彿是消耗民眾精力的玩具。
輸入法除了輸入文字以外,還有另一個重要用途是輸入特殊符號。自從Unicode興起之後,亟需發展一個能夠輸入各種特殊符號的輸入法。
如何製作input method?
製作輸入法,有個極大的難題:必須瞭解作業系統。當代的輸入法,由作業系統直接管轄。想要繪製選字視窗、想要將選好的文字傳送到目前開啟的軟體,都要依賴作業系統提供的API。
針對Windows作業系統,可以請教PCMan;針對Linux作業系統,可以請教酷音輸入法的貢獻者;針對瀏覽器,可以參考目前W3C正在制定當中的Input Method Editor API。
鍵盤按鍵與注音符號的對應表
1 -> ㄅ q -> ㄆ a -> ㄇ z -> ㄈ ...
起先有很多種鍵盤按鍵與注音符號的對應方式,不過現在只剩下一種了,就是鍵盤上看到那一種。
程式語言處理的其實是數字,我們建立的其實是「ASCII編號」與「注音符號編號」的對應表。
使用者敲打鍵盤、輸入ASCII編號,就換成注音符號編號。
亦得製作虛擬鍵盤,讓使用者點選滑鼠、輸入ASCII編號。Windows作業系統開啟注音輸入法,按下ctrl alt ,出現「螢幕小鍵盤」,那就是虛擬鍵盤。Android作業系統開啟任何輸入法,都會出現虛擬鍵盤。
注音符號與中文字的對應表
ㄅㄚ -> 八巴吧... ㄅㄚˊ -> 拔鈸跋... ㄅㄚˇ -> 把靶鈀... ㄅㄚˋ -> 爸霸壩... ㄅㄚ˙ -> 吧爸巴... ㄅㄛ -> 波撥剝... ㄅㄛˊ -> 伯柏泊... ...
注音符號的聲母21個、介母3個、韻母13個、聲調5種,拼音方式低於22×4×14×5 = 1540 < 2¹¹種。簡單的編碼方式是聲母5bit、介母2bit、韻母4bit、聲調3bit,拼成13bit,用2 byte的short變數記錄。
程式語言處理的其實是數字,我們建立的其實是「拼音編碼」與「Unicode編號」的對應表。
實務上如何得到這個表,我尚未調查清楚,麻煩讀者提供線索!我不清楚政府單位是否有公定公布這個表,我推測也許只能從開源專案獲得這個表,例如酷音輸入法。
注音符號與常用詞語的對應表
ㄅㄚ -> 八(199次) 吧(12次) ㄅㄚˋ ㄅㄚ˙ -> 爸爸(32次) ㄔㄤˊ ㄐㄧㄢˋ -> 常見(120次) 長劍(57次) ...
電腦自動選字、讀者手動選字,查表,列出最常用的詞語。表格的資料結構採用trie,可減少查表時間。
實務上如何得到這個表,我尚未調查清楚,麻煩讀者提供線索!有一種得到這個表的方式,是利用natural language領域的text segmentation,從網路上收集大量文章,以演算法自動斷詞,統計詞語出現次數。
詞語組合(斷詞與選詞)
一句話通常很長很長,不只一個詞語。電腦必須自動選擇正確的詞語組合。
ㄅㄚˋ ㄅㄚ˙ ㄇㄢˇ ㄔㄤˊ ㄐㄧㄢˋ 爸爸滿常見(O) 爸爸滿長劍(X) ㄅㄚˋ ㄅㄚ˙ ㄇㄞˇ ㄔㄤˊ ㄐㄧㄢˋ 爸爸買常見(X) 爸爸買長劍(O) ㄋㄧˇ ㄏㄨㄟˋ ㄧㄤˇ ㄕˋ ㄇㄚ˙ 你會癢是嗎(O) 你會仰式嗎(O)
簡單的方法:一、窮舉所有的詞語組合方式,找到最佳組合。二、greedy method令長詞優先配對。三、dynamic programming計算出現次數總和(或機率)最大的詞語組合。
複雜的方法:parse tree,分析語法語義。
折衷的方法:n-gram,建立詞語銜接詞語的對應表,同時記錄使用次數(或機率)。中文詞語林林總總,這個表非常大,需要超大型資料庫。
2-gram 爸爸 + 滿 -> 23次 爸爸 + 買 -> 30次 買 + 常見 -> 47次 買 + 長劍 -> 3次 滿 + 常見 -> 60次 滿 + 長劍 -> 2次 滿 + 長 -> 51次 ...
結語
全世界只有台灣在用注音符號,其他國家則用英文拼音。全世界只有台灣在用KK音標,其他國家則用IPA。想要深入鑽研輸入法的讀者,最好也研究一下其他國家的輸入法,以免故步自封。