0

昨日、この同様のスレッドを投稿しましたが、終了したと思っていましたが、テスト ケース 4/20 を実行するdecrypt1()と、Caesar class. では、次のテスト ケース (失敗) を実行すると、メソッドのコードのCaesar class何が問題なのかを突き止めようとしています。decrypt1()

@Test (timeout=2000)
public void test_Caesar_15(){
    assertEquals('Q',new CaesarCipher(100) .decrypt1('X'));
}

答えは、81私が得たものが のみの場合101です。別のケースは次のとおりです。

@Test (timeout=2000)
public void test_Caesar_21(){
    assertEquals("catfood",new CaesarCipher(17, lowerSpace).decrypt("trjweeu"));
}

出力があるべきときcatfoodですが、私はこのようにsmthになっていca fvvdます。smb は、decrypt1() メソッドで私を助けてくれますか/コードの修正に向けて私を案内してくれますか? Alphabet classAlphabet オブジェクトには、 に示されているすべての文字が含まれていると仮定しますDEFAULTdecrypt1()メソッドのバグを追跡しやすくするために、ここに 3 つの相互接続クラスを含めました。

public class CaesarCipher extends SymmetricCipher {

    protected int shift;

    public CaesarCipher(int shift, Alphabet alphabet)
    {
        super(alphabet);
        this.shift = shift;

    }

    public CaesarCipher(int shift)
    {

        super(Alphabet.DEFAULT);
        this.shift = shift;
    }

    public String encrypt(String s)
    {
        String encrypted = super.encrypt(s);
        return encrypted;


    }

    public char encrypt1(char c) throws NotInAlphabetException
    {

        int index = 0;
        int rotateIndex = 0;
        char shiftedChar = 0;

        index = alphabet.indexOf(c);
        if((index + shift) > alphabet.length())
        {
            rotateIndex = rotate(index, shift);
            shiftedChar = alphabet.get(rotateIndex);
        }
        else if((index + shift) < 0)
        {
            rotateIndex = rotate(index, shift);
            shiftedChar = alphabet.get(rotateIndex);
        }
        else
        {
            index += shift;
            shiftedChar = alphabet.get(index);
        }

        return shiftedChar;


    }

    public String decrypt(String s)
    {
        String decrypted = super.decrypt(s);
        return decrypted;
    }
    public char decrypt1(char c)
    {
        int index = 0;
        int rotateIndex = 0;
        char shiftedChar = 0;

        index = alphabet.indexOf(c);

        if((index - shift) > alphabet.length())
        {
            rotateIndex = rotate(index, shift);
            shiftedChar = alphabet.get(rotateIndex);
        }
        else if((index - shift) < 0)
        {

            rotateIndex = rotate(index, shift);
            shiftedChar = alphabet.get(rotateIndex);
        }
        else
        {
            index = index - shift;
            shiftedChar = alphabet.get(index);
        }

        return shiftedChar;
    }

    public String toString()
    {
        return "Caesar Cipher (shift="+shift+")";
    }

}


public abstract class SymmetricCipher extends Cipher {

    protected Alphabet alphabet;

    public SymmetricCipher (Alphabet alphabet)
    {
        this.alphabet = alphabet;
    }

    public int wrapInt(int i)
    {
        int index = 0;
        if (i >= alphabet.length())
            index = Math.abs(i) % alphabet.length();
        else if (i < 0)
        {
            int temp = Math.abs(i) % alphabet.length();
            index = alphabet.length() - temp;
        }
        else 
            index = i;

        return index;
    }

    public int rotate(int index, int shift)
    {
        int result = 0;

        if (shift > 0)
        {
            result = (index + shift) % alphabet.length();
        }

        else if (shift < 0)
        {
            if(index < Math.abs(shift))
            {
                int temp = Math.abs(index + shift);
                result = alphabet.length() - temp;

            }
            else 
                result = index + shift ;
        }   


        return result;
    }

    public Alphabet getAlphabet()
    {
        return this.alphabet;
    }

    public String encrypt(String s) 
    {
        String string = "";
        char c = 0;
        char encrypted = 0;
        for (int i = 0; i < s.length(); i++)
        {
            c = s.charAt(i);
            encrypted = encrypt1(c);
            string += encrypted;
        }
        return string;


    }

    public String decrypt(String s) throws NotInAlphabetException
    {
        String string = "";
        char c = 0;
        char decrypted = 0;
        for (int i = 0; i < s.length(); i++)
        {
            c = s.charAt(i);
            decrypted = decrypt1(c);
            string += decrypted;
        }
        return string;


    }

    protected abstract char encrypt1(char c);

    protected abstract char decrypt1(char c);


}

public class Alphabet {


    private String symbols;
    public static final Alphabet DEFAULT = new Alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 1234567890!@#$%^&*()_+-=[]{}\\|;:'\",./?<>");

    public Alphabet(String symbols)
    {
        this.symbols = symbols;
    }

    public int indexOf(char c) 
    {
        Alphabet temp = new Alphabet(symbols);
        for(int i = 0; i < symbols.length(); i++)
        {
            if(c == symbols.charAt(i))
                return symbols.indexOf(c) ;
        }

        throw new NotInAlphabetException (c, temp); 
    }

    public char get(int i) 
    {
        Alphabet temp = new Alphabet(symbols);
        char c = 0;
        if (i > this.symbols.length())
            throw new NotInAlphabetException (c, temp);
        else 
            return symbols.charAt(i);
    }

    public int length()
    {
        return symbols.length();
    }

    public String getSymbols()
    {
        return symbols;
    }

    public String toString()
    {
        return "Alphabet("+this.symbols+")";
    }

    public boolean equals(Object other)
    {
        if(other instanceof Alphabet)
        {
            Alphabet temp = (Alphabet) other;
            return this.symbols.equals(temp.symbols);

        }
        else 
            return false;
    }
}
4

1 に答える 1

0

懸念事項を少し分離するために、コードを少しリファクタリングしました。たとえば、decrypt1() および encrypt1() メソッドは、インデックスの差/合計 -/+ シフトをオンに切り替えます。しかし、このコードは論理的にはrotate()に属しています。これを念頭に置いて、decrypt1() と encrypt1() は明確な関数になります。

@Override
public char encrypt1(char c) throws NotInAlphabetException {

    int index = alphabet.indexOf(c);
    int rotateIndex = rotate(index, shift);
    char shiftedChar = alphabet.get(rotateIndex);

    return shiftedChar;

}

@Override
public char decrypt1(char c) {

    int index = alphabet.indexOf(c);
    int rotateIndex = rotate(index, -shift);
    char shiftedChar = alphabet.get(rotateIndex);

    return shiftedChar;
}

これは明らかに Caesar 暗号のコードです: 暗号化は文字を indexC = indexP + shift からシフトし、復号化は indexP = indexC - shift に戻します。これにより、シフトの重量がすべて回転に移動します。

回転が負のシフトをサポートするようになったことは、最も重要です。アルファベットのサイズによるシフトはシフトなしと同じであることに注意してください。したがって、シフトが正になるまでシフトにアルファベットのサイズを追加し続けることができます。シフトがアルファベットの外にインデックスをもたらす追加の特別なケースについてはすでに検討しました。次のローテーションは両方の問題を解決します。

public int rotate(int index, int shift) {

    while (shift < 0) {
        shift += alphabet.length();
    }

    return (index + shift) % alphabet.length();
}

下のスペースが

Alphabet lowerSpace = new Alphabet("abcdefghijklmnopqrstuvwxyz ");

上記の関数は、あなたが示した問題を解決します。スーパークラスに動的ディスパッチの明示的なレイヤーを不必要に追加しているだけなので、CaesarCipher で encrypt() と decrypt() をオーバーライドする必要はないことを指摘しておく必要があります。

于 2015-03-01T20:55:08.627 に答える