您好我正在开发一个cesar算法应用程序它不包含错误但我有特殊字符的问题我有正方形而不是相应的字符我也不知道如何处理我的代码中的空格< / p>
package cesar;
import java.util.Scanner;
public class Cesar {
private static short codeMajuscule=65;
private static short codeMinuscule=97;
private static short tailleAlph = 26;
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
System.out.println("Entrer la chaine a crypter");
String phrase = sc.next();
System.out.println("entrer votre cle");
int c= sc.nextInt();
System.out.println( "la phrase après transformation " + chiffrement( phrase , c ) );
}
private static String chiffrement( String ch , int n ){
String chDecripte="";
ch=ch.replaceAll("[éèêë]", "e");
ch=ch.replaceAll("[Ç]", "C");
ch=ch.replaceAll("[ÈÉÊË]", "E");
ch=ch.replaceAll("[ÌÍÎÏ]", "I");
ch=ch.replaceAll("Ñ", "N");
ch=ch.replaceAll("ÒÓÔŒ", "O");
ch=ch.replaceAll("ÙÚÛÜ", "U");
ch=ch.replaceAll("ÝŸ", "Y");
ch=ch.replaceAll("àáâæ", "a");
ch=ch.replaceAll("[ÀÁÂÆ]", "A");
ch=ch.replaceAll("[èéêë]", "e");
ch=ch.replaceAll("[ìíîï]", "i");
ch=ch.replaceAll("[ñ]", "n");
ch=ch.replaceAll("[òóôœ]", "o");
ch=ch.replaceAll("[ùúûü]", "u");
ch=ch.replaceAll("[ýÿ]", "y");
for( int i = 0 ; i < ch.length() ; i++ ){
if( ch.codePointAt(i) >= codeMajuscule &&
ch.codePointAt(i) <= ( codeMajuscule + tailleAlph ) ){
chDecripte += (char) ( ( ch.codePointAt( i ) - codeMajuscule + n ) % tailleAlph + codeMajuscule ) ;
}else if( ch.codePointAt(i) >= codeMinuscule &&
ch.codePointAt(i) <= ( codeMinuscule + tailleAlph ) ){
chDecripte += (char) ( ( ch.codePointAt( i ) - codeMinuscule + n ) % tailleAlph + codeMinuscule ) ;
}else{
chDecripte += ch.charAt( i );
}
}
return chDecripte;
}
}
并谢谢
答案 0 :(得分:0)
通常(并非总是)Cesar密码不考虑空格字符,它们会忽略任何空格和特殊字符,如句点,冒号,逗号等。如果您选择允许它们,您需要创建一个&#34;键&#34;或&#34;地图&#34;所以你知道如何撤消操作。
通常,可以使用数字表示(整数格式)操纵所有字符。如果将它们视为数字,这将成为一个更简单的问题。由于您使用的是特殊字符,我假设您使用的是UTF-8格式?您可以考虑对数值进行操作,并将此UTF-8图表用作&#34;地图&#34;:
如果您正在使用仅ASCII子集,请将此图表用作&#34;地图&#34;:
在执行Cesar密码时要考虑的事项通常是您希望保持在正常字母或某些指定字符子集的范围内。所以,当你到达这封信的时候,&#39; z&#39; (122整数值)如果你正在向右移动,你需要退回到&#39; a&#39; (97整数值)然后继续从那里转移。
例如,我们知道小写字母表中有26个数字,它们的范围是ASCII - 97 - 122.所以你可以像(伪代码)那样进行检查:
char char_to_shift; /* the character to be shifted */
if (char_to_shift + shift_amount > 'z') {
tmp = shift_amount - ('z' - char_to_shift);
shift_amount = tmp;
char_to_shift='a';
char_to_shift+=shift_amount;
} else {
char_to_shift+=shift_amount;
}
所以在上面的伪代码中,我们假设我们正在将一个字符5向右移位(ROT-5)并且该字符是&#39; x&#39; (120整数值)。我们会转移到125,这是&#39; {&#39;字符。相反,我们做的是&#39;&#39; (122) - &#39; x&#39; (120)给我们留下2.然后我们从shift_amount(5)中减去它,这样我们就剩下3.然后我们将char_to_shift重置为&#39; a&#39;并将剩余的金额3移到最后一个&#39; c&#39;
另请注意,如果您决定允许将小写字母转换为大写字母,则需要考虑大写字母和小写字母之间的间隙。
生成自己的&#34;价值图&#34;如果上面的表格不符合您的要求,请尝试打印允许字符子集中每个字符的十进制值。
答案 1 :(得分:0)
以下代码不正确:
...
}else if( ch.codePointAt(i) >= codeMinuscule &&
ch.codePointAt(i) <= ( codeMinuscule + tailleAlph ) ){
chDecripte += (char) ( ( ch.codePointAt( i ) - codeMinuscule + n ) % tailleAlph + codeMinuscule ) ;
}else{
chDecripte += ch.charAt( i );
}
首先,您的输入可能不是全部大写字符。但由于某种原因,第二条if线突然似乎倒数而不是上升。你应该只在解密期间这样做。 if语句也使用<=
和>=
,而=
字符显然已被前一个if
覆盖。
最后,永远不会达到最后一个else
,因为if
和else if
语句涵盖了它。
我已经创建了一个备用源代码,里面有一些提示:
import java.text.Normalizer;
import java.util.Scanner;
public class Cesar {
// unchanged
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Entrer la chaine a crypter");
String phrase = sc.next();
System.out.println("entrer votre cle");
int c = sc.nextInt();
System.out.println("la phrase après transformation " + chiffrement(phrase, c));
}
// you can directly show what you are doing by using 'A' and 'Z'
private static int CODE_MAJESCULE = 'A';
// you may actually not need constants for this
private static int CODE_MINESCULE = 'Z';
// the TAILLE_ALPH is of course the difference of those two
private static int TAILLE_ALPH = CODE_MINESCULE - CODE_MAJESCULE + 1;
// split out into separate methods whereever possible
private static String normalise(String phrase) {
// probably better to change Æ into AE
// but
String doublesRemoved = phrase.replaceAll("Æ", "a").replaceAll("Œ", "o");
doublesRemoved = doublesRemoved.replaceAll("æ", "a").replaceAll("œ", "o");
// separates character and diacritic (ë becomes e + " in a way)
String separated = Normalizer.normalize(doublesRemoved, Normalizer.Form.NFD);
// this will also remove all non-western characters
String accentsRemoved = separated.replaceAll("[^\\p{ASCII}]", "");
// and finally, we only seem to handle uppercase
return accentsRemoved.toUpperCase();
}
private static String chiffrement(String phrase, int cle) {
// first normalize the message so we can handle it
String phraseNormalise = normalise(phrase);
// use a StringBuilder (or the right size) for adding characters in loops
StringBuilder chiffre = new StringBuilder(phraseNormalise.length());
for (int i = 0; i < phraseNormalise.length(); i++) {
// codePointAt doesn't play nice with String.length()
// and it's now all ASCII anyway
char v = phraseNormalise.charAt(i);
// --- filter out special characters
if (v < CODE_MAJESCULE || v > CODE_MINESCULE) {
chiffre.append(v);
// most Java programmers use continue for "guards"
continue;
}
char c = cesar(v, cle);
chiffre.append(c);
}
// ... and return
return chiffre.toString();
}
private static char cesar(char v, int cle) {
// --- convert into element e in [0..TAILLE_ALPH)
int e = v - CODE_MAJESCULE;
// --- perform the cesar chiffre
int cc = (e + cle) % TAILLE_ALPH;
// --- convert back into A .. Z
char c = (char) (cc + CODE_MAJESCULE);
return c;
}
}
最重要的是,它在一个单独的行上执行凯撒密码。这样可以更容易地做到正确。
解决子问题中的问题(并单独测试)是编程中最重要的技能之一。永远不要忘记这样做。