我昨天发布了这个类似的帖子,认为我已经完成了它,但是当我运行测试用例4/20时,decrypt1()
方法的Caesar class
方法失败了。在Caesar class
中,如果我运行以下测试用例(失败),我试图找出我的decrypt1()
方法代码出了什么问题:< / p>
@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
时,我会像ca fvvd
那样获得smth。请问smb请帮我解密一下()方法/指导我修复代码?假设Alphabet对象包括Alphabet class
中显示为DEFAULT
的每个字符。我在这里包含了三个互连类,因此可以更容易地跟踪decrypt1()
方法中的错误。
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;
}
}
答案 0 :(得分:0)
我重构了一些你的代码以稍微分开一些问题。例如,decrypt1()和encrypt1()方法已经切换了索引 - / + shift的差异/总和。但是这段代码在逻辑上属于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。这会使所有重量转移到旋转状态。
旋转现在支持负向移动至关重要。请注意,按字母大小的移动与完全没有移位相同,因此我们可以继续将字母大小添加到移位,直到移位为正。您已经考虑了其他特殊情况,其中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(),因为您只是不必要地将一个显式的动态调度层添加回超类。