
上圖是用了如下的表格
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
沒有留言:
張貼留言