Text

Text

Text是由文字堆砌而成、可以閱讀的東西。

我們將Text打散為基本單位,以便理解Text:

從書寫的觀點:英文的基本單位叫做letter,即是ABC...這26種英文字母。中文的基本單位叫做,即是字典裡面那些字。

從語言的觀點:英文的基本單位叫做word,由一個以上的letter組成,例如apple、boy、cat。中文的基本單位叫做,由一個以上的字組成,例如蘋果、男孩、貓。

從電腦的觀點:基本單位叫做character,繁中譯作「字元」,簡中譯作「字符」。電腦可以處理的字元,主要是依據ASCIIUnicode的規定。英文字元有ABCDabcd1234,.!?等。中文字元包括了字典裡面那些字,以及ㄅㄆㄇㄈ。,、:等注音符號與標點符號;絕大部分的中文字都有收錄,只漏了一些冷僻的字。

在電腦螢幕上顯示字元,只要打開文字編輯器,選擇輸入法,用手指敲敲鍵盤即可。還可以進一步,將電腦螢幕上的字元,儲存到純文字檔案裡;將純文字檔案裡的字元,顯示在電腦螢幕上。

想要寫程式在電腦螢幕上顯示字元,只要運用scanf、printf、cin、cout,就會以Command-line Interface顯示字元。還可以進一步,寫程式將字元儲存到檔案;寫程式從檔案讀取字元。

想要處理字元,相關的學問有字串學編碼理論。相關的本站文件有StringCode

想要顯示字元,屬於Graphics的領域。

Font

Font就是文字的造型。譯作「字體」或「字型」。

電腦顯示字元,必須透過字型。只要有文字的地方,通常都能更換字型,例如文字編輯器、瀏覽器、作業系統、命令提示字元。可供選擇的字型,主要是看你的電腦安裝了哪些字型。

Text Editor

Text Viewer

文字閱讀器。閱讀純文字檔案的工具。

例如Unix系統的moreless指令。

Text Editor

文字編輯器。閱讀和編輯純文字檔案的工具。

例如NotepadVimUltraEdit

台灣人製造的文字編輯器:漢書Notepad++

程式設計師開發程式碼的工具軟體IDE,也包含文字編輯器:Microsoft Visual StudioCode::BlocksVS CodeAtom

文字編輯器的函式庫: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

網頁瀏覽器提供的圖形介面,開發文字編輯器。

利用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格式像是HTMLTEXRTF

以HTML為例,它藉由「標籤」來附加資訊。首先使用純文字編輯器讀取.html檔案,編輯Rich Text,然後使用瀏覽器讀取.html檔案,就變成美美的網頁了。

為了附加資訊,於是發明了保留字的概念:某些文字必須當作「此為附加資訊」的提示,不能當作純文字。

為了讓保留字也可以成為純文字,於是又發明了跳脫字元的概念:以罕見的文字組合,代替保留字。

以HTML為例,標籤不能當作純文字,例如<p>。如果想要顯示跟標籤一模一樣的純文字,就必須利用跳脫字元&:寫下&lt;就變成<,寫下&gt;就變成>,寫下&lt;p&gt;就變成<p>了。

聰明的讀者肯定馬上又想到:如果想要顯示&lt;的純文字呢?答案是跳脫字元本身也要設計跳脫字元:寫下&amp;就變成&,寫下&amp;lt;就變成&lt;。

Rich Text Editor

可以實際動手操作的範例:http://ckeditor.com/demo

用純文字編輯器來設計Rich Text,眼睛看著純文字、腦袋想著真實畫面,迂迴反直覺。於是有人提倡WYSIWYG(所見即所得)的概念:編輯器直接顯示真實畫面,使用者直接編輯真實畫面;編輯器根據使用者的操作過程,暗地裡生成Rich Text。

知名的富文字編輯器軟體,例如編輯RTF的Microsoft Word、編輯HTML的Adobe DreamWeaver。現在網路發達,也有很多人開發網頁版的富文字編輯器,例如CKEditorTinyMCE

很多IDE也有富文字編輯器,以便直覺地設計GUI程式,就是俗稱的「拉介面」。例如Microsoft Visual StudioC++BuilderQt Creator

程式語言已經內建了富文字編輯器,例如C#的RichTextBox、Qt的QTextEdit,我們可以直接拿來用。

文字是人類最擅長的媒體,富文字編輯器舉目皆是。即時通訊軟體SkypeLINE,社群網站Facebook,部落格網站WordpressMedium,微網誌網站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。想要深入鑽研輸入法的讀者,最好也研究一下其他國家的輸入法,以免故步自封。