上圖是用了如下的表格
cArray = {'q', 'z', 'i', 'r', 'a', 'j', 's', 'b', 'k', 't', 'c', 'l', 'u', 'd', 'm', 'v', 'e', 'n', 'w', 'f', 'o', 'x', 'g', 'p', 'y', 'h'};
對以下的字串而言
"There is no spoon.";
我們先來想一想程式應該如何完成這一項工作,首先, 'T' 不是英文小寫字母,因此跳過,然後 'h' 、 'e' 、 'r' 、 'e' 都是英文小寫字母,對照表格,需要轉換為 'b' 、 'a' 、 'n' 、 'a' ,接下來遇到一個空格字元 ' ' ,也跳過,然後 'i' 、 's' 也都是英文小寫字母,需要轉換為 'k' 、 'w' ,餘下類推。
所以需要利用一個迴圈 (loop) 進行上述編碼工作,逐一檢查字串中的每一個字元 (character) ,若是屬於英文小寫字母的編碼範圍,在 Unicode 就是 97 到 122 之間,先將該字元轉換為整數,然後減掉 97 就會是表格中對應字元的 Unicode 編碼值。
這是說,第 0 個字元(索引值為 0 ) 'T' 不在英文小寫字母編碼的範圍,因此程式不會處理,然後到第 1 個字元 'h' ,這是英文小寫字母編碼為 84 ,減去 97 之後為 7 ,對應到上面的表格會是 'b' ,因此得到的新字串第 1 個新字元就是 'b' ,餘下會一直進行重複的工作到字串結束為止。
因此,我們對編碼方法 (method) 設計如下
public string toEncode(string s) { System.Text.StringBuilder r = new System.Text.StringBuilder(); // 進行編碼轉換 char c; int i, m; for (i = 0; i < s.Length; i++) { if (s[i] >= 97 && s[i] <= 122) { c = s[i]; m = c - 97; r.Append(this.Code[m]); } else { r.Append(s[i]); } } // 回傳字串 return r.ToString(); }
toEncode() 接收一個字串當參數,也回傳一個新字串。我們在 toEncode() 建立一個暫存的 StringBuilder ,這是因為字串被設計成不可變的 (immutable) ,也就是說,字串一旦被建立後,就不能再被更改內容,所以藉由可變的 StringBuilder 來進行這項工作,最後再回傳字串。
進行編碼轉換的迴圈
// 進行編碼轉換 char c; int i, m; for (i = 0; i < s.Length; i++) { if (s[i] >= 97 && s[i] <= 122) { c = s[i]; m = c - 97; r.Append(this.Code[m]); } else { r.Append(s[i]); } }
字串的屬性 (property) Length 為字串中元素的個數,迴圈的控制變數 i 最大不超過 s.Length ,因為陣列索引從 0 開始,最後一個元素的索引為 Length - 1 。留意這一行
if (s[i] >= 97 && s[i] <= 122) {
只有英文小寫字母,也就是 Unicode 字元編碼在 97 到 122 之間,才會進行編碼轉換。底下第一個動作
c = s[i];
由 c 取得 s 中的元素,然後
m = c - 97;
m 為該字元為第幾個英文字母,這可直接對應到表格,因此用 m 取得表格中的元素,亦即要轉換的字元
r.Append(this.Code[m]);
若非英文小寫字母,也就是 Unicode 字元編碼在 97 到 122 之外,就直接將該字元加進 r 之中
r.Append(s[i]);
完整的 Encrypt 修改如下
class Encrypt { private string cArray; public string Code { get { return cArray; } set { if (value is string && value.Length == 26) { cArray = value; } else { System.Console.WriteLine("something worng!!");; } } } public Encrypt() { System.Random r = new System.Random(); int a = 0; int b = 0; // 限定 a 為偶數 while (a % 2 == 0) { a = r.Next(1, 10); b = r.Next(1, 10); } System.Console.Write("a: " + a + ", b: " + b + ", "); int x, y, m; char c = 'a'; int i; System.Text.StringBuilder s = new System.Text.StringBuilder(); for (i = 0; i < 26; i++) { x = c; y = x * a + b; m = y % 26; s.Append((char) (m + 97)); c++; } this.cArray = s.ToString(); } public string toEncode(string s) { System.Text.StringBuilder r = new System.Text.StringBuilder(); // 進行編碼轉換 char c; int i, m; for (i = 0; i < s.Length; i++) { if (s[i] >= 97 && s[i] <= 122) { c = s[i]; m = c - 97; r.Append(this.Code[m]); } else { r.Append(s[i]); } } // 回傳字串 return r.ToString(); } static void Main() { string s = "There is no spoon."; for (int i = 0; i < 16; i++) { Encrypt e = new Encrypt(); System.Console.WriteLine(i + ": "+ e.toEncode(s)); System.Threading.Thread.Sleep(1000); } } } /* 《程式語言教學誌》的範例程式 http://pydoing.blogspot.com/ 檔名:encrypt.cs 功能:示範 C# 程式 作者:張凱慶 時間:西元 2012 年 10 月 */
我們只對 "There is no spoon." 進行編碼,總共 16 次,每一次採用不同的轉換表格。測試結果如下
接下來,我們繼續加入解碼的功能吧!
中英文術語對照 | |
---|---|
編碼 | encoding |
字串 | string |
陣列 | array |
迴圈 | loop |
字元 | character |
方法 | method |
不可變的 | immutable |
屬性 | property |
您可以繼續參考
軟體開發
相關目錄
回 C# 入門指南
回 C# 教材
回首頁
參考資料
http://msdn.microsoft.com/zh-tw/library/ms173109%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/x9afc042.aspx
http://msdn.microsoft.com/zh-tw/library/ms229036%28v=vs.80%29.aspx
http://msdn.microsoft.com/zh-tw/library/0b0thckt.aspx
沒有留言:
張貼留言