编写程序,要求输入一个字符串,然后输入一个句子作为凯撒加密算法的密钥,然后输出该字符串加密后的结果。
举例如下:使用改进版caesar密码,密钥为I love my country!,明文为I am in danger!,计算出密文。
小写明文字母和大写密文字母的映射关系表如下图1,构造方法如下:第一行明文字母填写就是26个字母按顺序写,第二行密文字母顺序就是先把密钥句子(I love my country,注意重复字母去掉)写入密文字母里,然后再清点26个字母中没有写进密文的剩下字母按照字母表顺序依次写完。
明文 |
a |
b |
c |
d |
e |
f |
g |
h |
i |
j |
k |
l |
m |
n |
o |
p |
q |
r |
s |
t |
u |
v |
w |
x |
y |
z |
密文 |
I |
L |
O |
V |
E |
M |
Y |
C |
U |
N |
T |
R |
A |
B |
D |
F |
G |
H |
J |
K |
P |
Q |
S |
W |
X |
Z |
|-----密钥句子去掉重复字母-----||---26个字母剩下的按字母表顺序写入---|
图1 小写字母的映射表
因为密文是去掉标点符号后全部都是大写输出,究其原因是为了敌人(破译者)根据空格和标点符号和首字母大写等习惯猜出哪些字母在一起是一个完整单词。所以我们译文要去掉所有标点符号而且把所有字母都变成大写。所以根据图1我们得出图2大写字母对应的映射表,就是把图1的第一行全部变成大写即可。
明文 |
A |
B |
C |
D |
E |
F |
G |
H |
I |
J |
K |
L |
M |
N |
O |
P |
Q |
R |
S |
T |
U |
V |
W |
X |
Y |
Z |
密文 |
I |
L |
O |
V |
E |
M |
Y |
C |
U |
N |
T |
R |
A |
B |
D |
F |
G |
H |
J |
K |
P |
Q |
S |
W |
X |
Z |
|-----密钥句子去掉重复字母-----||---26个字母剩下的按字母表顺序写入---|
图2 大写字母的映射表
有了映射关系表,然后明文为I am in danger!,密文为UIAUBVIBYEH,注意密文一定是大写,所以密文是去掉标点符号后所有大小写都变成大写的密文输出。
代码实现:
/* 实现进阶版凯撒密码 */ import java.util.ArrayList; import java.util.Scanner; public class Caesar { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("明文:"); String mingwen = sc.nextLine(); System.out.print("密钥:"); String key = sc.nextLine(); String st = kaesarUpVersion(removeSymbol(mingwen),getKey(removeSymbol(key))); System.out.println("密文:"+st); } //实现将其他字符删除 public static String removeSymbol(String s){ //创建一个字符串生成器 StringBuilder sb = new StringBuilder(); //遍历字符串s for (int i = 0; i <s.length() ; i++) { //取出字符串中的每个字符 char ch = s.charAt(i); //如果字符是字母,添加到字符串生成器 if ((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){ sb.append(ch); } } //转换成字符串 String str = sb.toString(); return str.toUpperCase();//以大写字母返回 } //传入一个字符串,实现密文,并以大写字符串形式返回 public static String getKey(String string){ //创建一个动态数组对象 ArrayList<String> list = new ArrayList<>(); //遍历字符串 for (int i = 0; i <string.length() ; i++) { //用substring取出单个字符,并变为大写,赋值给st String st = string.substring(i,i+1).toUpperCase(); //使用contains函数,对数组内元素进行比较,皆不同时,添加进数组 if (!list.contains(st)){ list.add(st); } } //添加剩余的字母,形成映射表 for (char i = 65; i <=90 ; i++) { //valueOf函数将char类型转化为String类型 String str = String.valueOf(i); if (!list.contains(str)){ list.add(str); } } //创建字符串生成器对象 StringBuilder stringBuilder = new StringBuilder(); //将list数组的元素依次添加到生成器中 for (String s : list) { stringBuilder.append(s); } //转换为字符串,并返回 String end = stringBuilder.toString(); return end; } //根据明文和密钥,进行加密 public static String kaesarUpVersion(String s, String key){ //将字符串转换成char类型的数组 char[] charS = s.toCharArray(); char[] charKey = key.toCharArray(); //创建字符串生成器 StringBuilder builder = new StringBuilder(); //遍历明文字符数组,由对应关系产生密文 for (int i = 0; i <charS.length ; i++) { int j = charS[i]-65; builder.append(charKey[j]); } //转换为字符串并输出 String miwen = builder.toString(); return miwen; } }