2017-01-27 84 views
0

嗨,我正在開發一個塞薩爾算法的應用程序不包含錯誤,但我有特殊字符我有方形的,而不是相應的字符的問題也我不知道如何應對的空間我的代碼加密算法塞薩爾

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

你能給出一個示例輸入和輸出來顯示你的問題嗎? – coolioasjulio

+0

例如當我寫élève或類似的東西時,我有空的方塊代替specil caracter,我想要解碼,當我用空格寫東西時我有錯誤,因爲空間的情況在我的代碼 –

+0

這可能是您的空間錯誤的原因,但是您不使用新行分隔符。用'sc.nextLine()'替換'sc.next();',這將消耗整行輸入。 next()只在下一個空間消耗輸入。 – coolioasjulio

回答

0

通常(並不總是)塞薩爾密碼不佔空間的人物,他們忽略任何空格和特殊字符,例如句號,冒號,逗號等,如果你選擇允許他們,你需要創建一個「關鍵」或「地圖」,讓你知道如何撤消操作。

通常,所有的字符可使用它們的數字表示(整數格式)來操縱。如果你把它們當作數字來處理,這就變成了一個更簡單的問題。既然你使用特殊字符,我假設你使用的是UTF-8格式?你可能會考慮在數值操作和使用UTF-8圖表作爲「地圖」:

http://www.utf8-chartable.de/

如果你曾經用ASCII只子集使用該圖表工作作爲一個「地圖」:

http://www.asciitable.com/

事情做一個塞薩爾密碼時需要考慮的是,你通常要保持在正常的字母或字符的某些特定子集的範圍內。所以,當你到達字母「Z」(122的整數值),如果你是右移,你需要回到下降到「A」(97整數值),然後繼續從那裏轉移。

例如,我們知道有在小寫字母爲26位數,它們的範圍從97 ASCII - 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)和該字符是「X」(120的整數值)。我們將轉移到125這是'{'字符。相反,我們做「Z」(122) - 「X」(120),留下了一個2。然後我們減去從shift_amount(5),所以我們只剩下3。然後我們重置char_to_shift到「a」和將剩餘的數量3移至「c」。

另請注意,如果您決定允許將小寫字母轉換爲大寫字母,則需要考慮大寫字母和小寫字母之間的差距。

要生成您自己的「值映射表」,只要嘗試在允許的字符子集中打印出每個字符的十進制值(如果上述表格不符合要查找的內容)。

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所覆蓋。

最後,最後一個else將永遠不會被達到,因爲它涵蓋ifelse 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; 
    } 
} 

最重要的是它執行凱撒密碼本身在單獨的行。這使事情變得更容易。

分解子問題中的問題(並單獨測試)是編程中最重要的技能之一。永遠不要忘記這樣做。

+0

非常感謝,但是現在,當我在結果中輸入特殊字符時,它將被刪除,空間不受處理我輸入時出現錯誤 –

+0

是的,您必須決定要麼擴大字母*或保留或刪除角色。另一個錯誤已經存在於你自己的代碼中,只需將'next()'替換爲'nextLine()'作爲'next()'就可以讀取下一個空格。原始的凱撒密碼僅適用於包含常用字符的單個字母表。 –