Java 入門指南 - 解碼

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




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


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

    // 將字元陣列儲存為字串 
    for (i = 0; i < cs.length; i++) {
        cc = new Character(cs[i]);
        rs = rs.concat(cc.toString());
    }
        
    return rs;        
}


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


toDecode() 與 toEncode() 相似,同樣需要一個字串 (string) 當參數 (parameter) ,結果也回傳一個字串,並且一樣將字串先以 toCharArray() 方法轉換成字元陣列 (array) ,然後才開始進行解碼轉換工作。


解碼轉換由巢狀迴圈的部份來進行
// 進行解碼的工作    
for (i = 0; i < cs.length; i++) {
    // 判斷是否為英文小寫字母
    if (cs[i] >= 97 && cs[i] <= 122) {
        // 找出表格中對應的索引值
        for (j = 0; j <= getArray().length; j++) {
            if (cs[i] == getArray()[j]) {
                cs[i] = (char) (j + getDif());
                break;
            }
        }
    }
}


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


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


我們只增加一個 toDecode() 方法,完整的 Encrypt 類別可以參考 Encrypt.java


EncryptDemo 需要修改,然後才可對 toDecode() 進行測試
// 測試 Encrypt 的類別
public class EncryptDemo {
    public static void main(String[] args) {
        System.out.println();
        
        String s[] = {"There is no spoon.",
                      "It is all around us.",
                      "Free your mind.",
                      "Follow the white rabbit.",
                      "Choice. The problem is choice.",
                      "Action, reaction. Cause, effect.",
                      "Everything that has a beginning has an end.",
                      "Because I choose to."};        
        Encrypt e = new Encrypt();
        String t = "";
        for (int i = 0; i < 8; i++) {
            t = e.toEncode(s[i]);
            System.out.println(t);
            t = e.toDecode(t);
            System.out.println(t);
        }
         
        System.out.println();
    }
}

/* 《程式語言教學誌》的範例程式
    http://pydoing.blogspot.com/
    檔名:EncryptDemo.java
    功能:示範 Java 程式 
    作者:張凱慶
    時間:西元 2011 年 4 月 */


我們在電影駭客任務 The Matrix 系列中找了八個著名對白,儲存在字串陣列 s[] 之中,然後用一個 for 迴圈將每一句對白先編碼,印出編碼的結果,再把編碼後的字串解碼,然後印出還原後的字串,如果還原後的字串與 s[] 裡頭的相符,就表示我們的解碼方法是正確的。


記得, Encrypt 與 EncryptDemo 兩個類別都修改過,因此需要先編譯才可執行



嗯,編碼與解碼都正確無誤,接下來,我們先不談如何發展圖形介面,先討論一下 Java 組織程式原始碼檔案的套件吧!


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


您可以繼續參考
軟體開發


相關目錄
回 Java 入門指南
回 Java 教材目錄
回首頁


參考資料
The JavaTM Tutorials: Getting Started
The JavaTM Tutorials: Learning the Java Language
The JavaTM Tutorials: Essential Classes
The Java Language Specification, Third Edition


本文於 2013 年 1 月訂正

2 則留言:

symis 提到...

問1:
for (j = 0; j <= getArray().length; j++) {
的 j<= 是否應該是 j< 才對?
問2:
for (int i = 0; i < 8; i++) {
其中的8,是否改為s.length較好?
謝謝指導!

Kaiching Chang 提到...

關於問1 ,是的,完全正確的寫法是要寫成 < 而非 <= ,倒是這裡寫成 <= 並不會出錯。

關於問2 ,如果程式是接受未知大小的字串陣列,自然用 s.length 會比較合適,但若已經確定大小,直接用數字就已經有清楚的語意。