C# 入門指南 - 解碼

解碼 (decoding) 需要用到與編碼相同的轉換表格




所謂的解碼也就是將編碼 (encoding) 過的小寫英文字母回覆成原來的英文小寫字母,由上圖可以看出,我們儲存表格所用的字元陣列 (array) ,恰巧依索引值 (index) 可推回原來的英文小寫字母,這是說,索引值 0 為 'q' ,所以是將原本的 'a' 變成 'q' ,因此,解碼就是依索引值重新加上 97 即可。


實際上我們需要用到巢狀迴圈 (nested loop) ,也就是在迴圈 (loop) 中有其他的迴圈,對單一英文句子而言,我們需要一個迴圈判斷每個字元是否為英文小寫字母,若是英文小寫字母,我們就需要另一個迴圈找出對應的索引值。由這樣的概念設計的解碼方法 (method) toDecode() ,如下
public string toDecode(string s) {
    System.Text.StringBuilder r = new System.Text.StringBuilder();
            
    // 進行解碼的工作
    int i, j;
    for (i = 0; i < s.Length; i++) {
        if (s[i] >= 97 && s[i] <= 122) {
            // 找出表格中對應的索引值
            for (j = 0; j < 26; j++) {
                if (s[i] == this.Code[j]) {
                    r.Append((char) (j + 97));
                    break;
                }
            }
        }
        else {
            r.Append(s[i]);
        }
    }
    
    return r.ToString();
}


巢狀迴圈是迴圈中包含另一個迴圈,由於我們利用縮排的方式編輯程式碼,看起來內層迴圈像是凹陷進去的巢,故稱之為巢狀迴圈。


toDecode() 與 toEncode() 相似,同樣需要一個字串 (string) 當參數 (parameter) ,結果也回傳一個字串。


解碼轉換由巢狀迴圈的部份來進行
for (i = 0; i < s.Length; i++) {
    if (s[i] >= 97 && s[i] <= 122) {
        // 找出表格中對應的索引值
        for (j = 0; j < 26; j++) {
            if (s[i] == this.Code[j]) {
                r.Append((char) (j + 97));
                break;
            }
        }
    }
    else {
        r.Append(s[i]);
    }
}


外層迴圈會依序取得英文句子的每個字元,然後判斷是否為英文小寫字母,如果該字元是英文小寫字母,就會啟動另一個迴圈找出表格中對應的索引值出來,相反地,如果該字元不是英文小寫字母,控制變數 i 就會自動遞增,然後判斷下一個字元。


注意,這個巢狀迴圈用了兩個 for 、兩個 if ,依順序 forifforif ,這是我們打算讓程式執行的順序,若是沒有依照這樣的順序,程式可能會跑出無法預期的結果。


完整的 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();
    }
    
    public string toDecode(string s) {
        System.Text.StringBuilder r = new System.Text.StringBuilder();
            
        // 進行解碼的工作
        int i, j;
        for (i = 0; i < s.Length; i++) {
            if (s[i] >= 97 && s[i] <= 122) {
                // 找出表格中對應的索引值
                for (j = 0; j < 26; j++) {
                    if (s[i] == this.Code[j]) {
                        r.Append((char) (j + 97));
                        break;
                    }
                }
            }
            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." 編碼、解碼了八次,編譯執行結果如下



嗯,編碼與解碼都正確無誤,接下來,我們先不談如何發展圖形介面,先討論一下 C# 組織程式原始碼檔案的方式,這需要先討論一下程式結構


中英文術語對照
解碼decoding
編碼encoding
陣列array
索引值index
巢狀迴圈nested loop
迴圈loop
方法method
字串string
參數parameter


您可以繼續參考
軟體開發


相關目錄
回 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

2 則留言:

Unknown 提到...

在Main裡面好像少了toDecode的呼叫
這樣應該沒辦法得到如圖的執行結果吧??

Unknown 提到...

System.Console.WriteLine(i + " toDecode: " + e.toDecode(e.toEncode(s)));

Main多加一行