在製作 中文轉羅馬拼音之前 必須先了解其中的原理!
當我們再輸入 鍵盤同時 將傳送一組 字串
比如說 要將 林哲健 轉成 羅馬拼音
首先收到這組字串 林哲健
在個別將國字 做比對 林=xup6 哲=xup6 健=ru04
再用這組字串 轉換成注音 變成 ㄌ一ㄣˊ ㄓㄜˊ ㄐㄧㄢˋ
再將注音 正規化 去除 ˇ ˋˊ ˙
然後 開始比對 注音 將得到羅馬拼音
ㄌ一ㄣ= LIN
ㄓㄜ =je
ㄐㄧㄢ=Jian
那麼 中文字 10萬多個字 及 很多種比對資料
甚至更多 我們要如何將資料
有效率的存取與調用呢??
這時就 必須使用到 SQL 資料庫
在收集資料 比較痛苦一點
網路上雖然有很多 羅馬拼音 與 注音的 資料表
但是卻很少 英文 與注音 的比對的資料表
這裡可能要辛苦找一下
接下來資料有了 整理成一個 Access檔
Access檔 裡面有三個 資料表 我大概 講解一下
第一個 字轉Key 有國字 及 鍵盤碼
比如 尺 = t3 建=ru04 帥=gj94
第二個 符號轉注音 有 符號 與 注音
比如 1= ㄅ Q=ㄆ A=ㄇ
第三個 注音轉拼音 有注音 與 羅馬拼音
比如 ㄌ一ㄣ= LIN ㄓㄜ =je ㄐㄧㄢ=Jian
簡單來說 我們只是把 資料 輸入進去 經由 比對 再把結果送出
原理就這麼簡單!!
儘管簡單 收集資料卻很痛苦 不過做完很有成就感 !
開始來看範例吧
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Data;
using System.Data.OleDb;
namespace ChineseToABC
{
public partial class Frm_Main : Form
{
//首先 建立 全域的connection連線物件
OleDbConnection conn = new OleDbConnection
(//連線物件+來源
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + "中文轉羅馬.accdb"
);
//再來 建立 全域性的 SQL查詢指令字串
string SelectCmd;
//存放比對結果的字串
string re = "";// 存放 輸入的英文+符號數字
string OKGO = "";//存放 注音
string STAR = "";//存放 羅馬拼音
public Frm_Main()
{
InitializeComponent();
}
來看上列程式碼 一樣 註解 已經 很清楚了!
基於備忘 還是在特別說一次好了
首先!!
程式啟動同時 會先 宣告 全域物件
為了要多次比對字串 為了方便
宣告全域 資料庫connection連線物件 conn
SQL指令需要多次變化也宣告全域selectedCmd
以及
三個 字串 存放 羅馬 注音 與 英文字
如果像是 中文名子三個國字以上
由於資料庫國字是個別處理 全域的字串可以方便累加上去
在事件觸發之前 先講解一下 視窗控制元件 防備忘
三個 label1~3 分別為 1英文字符號 2注音 3羅馬
一個 textbox1 輸入中文用
一個 BUTTON2 觸發用
OK! 假如現在 在 textbox1 中 輸入:林
按下 BUTTON2
來看下列程式碼!
private void button2_Click(object sender, EventArgs e)
{
re = ""; //清除上一次使用的字串
OKGO = "";//清除上一次使用的字串
STAR = "";//清除上一次使用的字串
if (textBox1.Text != string.Empty)//判斷是否空直
{
GO(textBox1.Text);//呼叫副程式(帶摻數)
}
else
{
MessageBox.Show("請輸入中文字");
}
}
s sss
re okgo star 這些字串 先歸零 因為 上一次 觸發 字串中還殘留 收尋結果
if (textBox1.Text != string.Empty)判斷是否是空值
不是直接呼叫 GO(textBox1.Text)副程式
並且 帶入剛剛在textBox1.Text輸入的中文
再來 來看 GO() 副程式 如何運作
private void GO(string x)
{
for (int i = 0; i <= x.Length - 1; i++)
{
conn.Open();//開啟資料庫
//string SelectCmd2="Select*form 注音轉符號 Whrer 符號='"++"'";
SelectCmd = "Select*from 字轉KEY Where 字='" + x[i] + "'";//設定查詢語法並加入輸入的中文x
//將查詢x那一列的所有資料
OleDbCommand Cmd = new OleDbCommand(SelectCmd, conn);//建立命令加入 語法+連線物件
OleDbDataReader reader = Cmd.ExecuteReader();//ExecuteReader()是將Command查詢語法傳入connection中
while (reader.Read())
//OleDbDataReader 的預設位置在第一個資料錄之前。因此,您必須呼叫 Read 以開始存取任何資料。
{
re += reader["欄位2"].ToString()+" ";
TOTO(reader["欄位2"].ToString());
}
label1.Text = "你輸入的KEY是:" + re;
conn.Close();
}
}
來看GO(string x)中的x
是剛剛輸入的
textBox1.Text
而第一個 for (int i = 0; i <= x.Length - 1; i++)
是要來判斷 幾個國字 方便 個別搜尋資料庫 假設只有一個字"林"
conn.Open();
再來開啟在全域宣告的資料庫
SelectCmd = "Select*from 字轉KEY Where 字='" + x[i] + "'";
將x[0] 帶入 查詢第一個字 假設是"林"
OleDbCommand Cmd = new OleDbCommand(SelectCmd, conn)
建立命令物件 他需要 命令物件+連線物件
OleDbDataReader reader = Cmd.ExecuteReader()
再來將 命令 傳送給 連線物件 再指派給OleDbDataReader 讀取用
while (reader.Read())
{
re += reader["欄位2"].ToString()+" ";
TOTO(reader["欄位2"].ToString());
}
reader.Read此方法 為 是否讀取到資料 裡面有資料將回傳 true
re是將 查詢到的資料 的隔壁叫(欄位2)裡的值放入re中
欄位一是:"林" 欄位二是: "XUP6"
而 (累加)+= 是因為 如果 有1個字以上 將會累加到re上
最後再把re 給label!!
再來 TOTO(reader["欄位2"].ToString()); 將查詢結果
再次呼叫副程式!
而本程式週期 因再次呼叫了 副程式
所以要等TOTO()執行完回傳 數據
才能將 此區塊結束!!
注意喔!! 此區況 尚未結束 所以
label1.Text = "你輸入的KEY是:" + re;
conn.Close();
這部分 都尚未執行!!
再來我們來看TOTO()中 做了甚麼處理
我們知道TOTO(reader["欄位2"].ToString());
帶入的參數 是一組 林的 "XUP6" key碼
而在TOTO() 裡面只是將 key轉成 注音 而已
來看下列程式碼!
private void TOTO(string s)
{
string yy = "";
char[] arr = s.ToCharArray(0, s.Length);
foreach (char c in arr)
{
SelectCmd="Select*from 注音轉符號 Where 符號='"+c+"'";
OleDbCommand Cmd = new OleDbCommand(SelectCmd, conn);
OleDbDataReader reader = Cmd.ExecuteReader();
while (reader.Read())
{
yy += reader["注音"];
}
}
OKGO += yy+" ";
label2.Text = "你輸入的注音是:" + OKGO;
end(yy);
}
來看
TOTO(string s)
"s"是剛剛傳入的 "XUP6"
再來為了將每一個字元做 資料庫獨立搜尋
我們利用ToCharArray 將字串 放進 char[]陣列中
s.ToCharArray(0, s.Length);
s是字串0是起始位置 S.Length是 s字串長度
然後轉成char
然後 再利用foreach (char c in arr)
將arr[]陣列 放進c
在來 foreach區塊內
修改全域的SQL指令 SelectCmd 將c套入指令中!
SelectCmd="Select*from 注音轉符號 Where 符號='"+c+"'";
再來 建立OleDbCommand 和 OleDbDataReader
OleDbCommand Cmd = new OleDbCommand(SelectCmd, conn);
OleDbDataReader reader = Cmd.ExecuteReader();
然後一樣 reader.Read() =true 啟動!
while (reader.Read())
{
yy += reader["注音"];
}
然後在foreach區塊內 C[]會不斷變化
使得
while區塊內的yy會不斷累加!!
直到 將字元完整收巡完畢 才跳出區塊
來看剩下的程式碼
OKGO += yy+" ";
label2.Text = "你輸入的注音是:" + OKGO;
end(yy);
將查詢結果 累加OKGO
為何累加? 因為 TOTO(string s)只將一子字轉成注音
等等還會有第二個字 第三個字 送入這TOTO()
全域的OKGO 將會 把結果累加成一個完整的 名子
label2 將答案顯示
end(yy) 將注音 傳送給!第三個副程式
再來我們來看看end(yy) 中的程式碼
是如何轉 羅馬拼音的
private void end(string er)
{
string pattern = "[ˇˋˊ˙]";//把ˇˋˊ˙濾掉
string replacement = "";//如果找到ˇˋˊ˙替代成空字元
Regex rgx = new Regex(pattern);//建立正規化 套入pattern過濾條件
string result = rgx.Replace(er, replacement);//er是注音result是已將ˇˋˊ˙濾掉的字串
SelectCmd = "Select*from 注音轉拼音 Where 注音='" + result + "'";
OleDbCommand Cmd = new OleDbCommand(SelectCmd, conn);
OleDbDataReader reader = Cmd.ExecuteReader();
while (reader.Read())
{
STAR += reader["羅馬拼音1"]+" ";
}
label3.Text = "轉羅馬的英文是:" + STAR;
}
sas as a
string er是上一個副程式 所搜尋的結果 是注音
但是 資料庫中 比對的注音 並無ˇˋˊ˙
所以我們在這邊需要用到一個 過濾方法
叫做 正規化
原理是將 ㄌ一ㄣˊ 轉成 ㄌ一ㄣ
然後再比對資料庫
此 副程式 只有多了正規化 其他都 大同小異
後續不做介紹
此程式結束後 將 遞迴到GO()
而TOTO()已經運算結果回傳完畢 跳出區塊
關閉資料庫 CONN.CLOSE
在跳出 FOR迴圈
如果FOR迴圈中的X還有其他字元 將會在執行一次上續動作
private void GO(string x)
{
for (int i = 0; i <= x.Length - 1; i++)
直到i=字元長度 中指for迴圈
完!