2011-03-17 11 views
2

所以我最近決定我的編碼風格有點笨拙。麻煩的是,我似乎無法走到一個階段,在那裏我可以找到將其簡化爲更少效率代碼的方式。如何簡化我的凱撒移位加密算法c#的實現?

我是在一個團隊編碼情況前些天試圖代碼使用TDD一個自動換行功能。當我坐在駕駛座位上時,我大部分時間都在使用String.Split()和if語句。我在編碼的那個人問爲什麼這麼複雜,然後用簡單的遞歸單線程返回所需的值,並用一些條件在完成時將他從遞歸循環中引導出來。

所以我的問題是這樣 - 下面是一些代碼,我已經寫上做只使用小寫字母和空格的字符串輸入凱撒移位加密。單元測試通過,我相信我已經實現了可能發生的各種情況。

在堅果殼會怎麼你們簡化下面的代碼,以使其更具可讀性,更高效?

我很欣賞這個的幫助,因爲在這一天,我需要讓我的編碼風格更簡潔和更簡單的和無法弄清楚,以最好的地方開始的結束。

乾杯

代碼在C#:

public static string Encrypt(string inputString, int shiftPattern) 
    { 
     StringBuilder sb = new StringBuilder(); 

     char[] alphabet = { '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' }; 

     //y = x + 3 (mod 26) 
     foreach (var letter in inputString.ToLower()) 
     { 
      if (!alphabet.Contains(letter)) 
      { 
       return "The " + letter + " Character was not in the sample set, please ensure you only use letters"; 
      } 

      var res = Array.IndexOf(alphabet, letter) + (shiftPattern % 26); 

      if (res >= 26) 
      { 
       res = res - alphabet.Length; 

       sb.Append(alphabet[res]); 
      } 

      else if (res < 0) 
      { 
       res = alphabet.Length + res; 
       sb.Append(alphabet[res]); 
      } 

      else 

       sb.Append(alphabet[res]); 
     } 
     return sb.ToString(); 
    } 
+6

我會建議http://codereview.stackexchange.com/,他們會給你想要的東西。 – Snowbear 2011-03-17 09:32:53

+0

+1 Snowbear ...我不知道codereview! :D – Jonathan 2011-03-17 09:42:41

+0

啊 - 不知道那個網站。感謝您的高舉。如果你在一個負數傳遞 – Morn 2011-03-17 10:03:56

回答

2

1.-將sb.Append(字母表[RES])只有一次外的條件句。
2.-考慮拋出一個異常,而不是返回一條消息...所以稍後您可以輕鬆地檢查該操作是否有效。如果您的字母定義中未包含該字符,您還應該考慮讓字符「原樣」。它將允許你處理空白等。
3.-檢查最後的條件是否真的有必要。初看......看起來它可能被安全刪除......所以確認一下。我們可以添加一個Math.Abs​​函數來避免ShiftPattern中負數的問題。
4.-在某些地方使用alphabet.Length,在其他地方使用26.使用always.Length。
5.-不檢查(res> = 26),你可以直接進行MOD操作。

public static string Encrypt(string inputString, int shiftPattern) 
      { 
       StringBuilder sb = new StringBuilder(); 

       char[] alphabet = { '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' }; 

       //y = x + 3 (mod 26) 
       foreach (var letter in inputString.ToLower()) 
       { 
        if (!alphabet.Contains(letter)) //Consider throwing and exception instead 
        { 
         return "The " + letter + " Character was not in the sample set, please ensure you only use letters"; 
        } 

        var res = Array.IndexOf(alphabet, letter) + (Math.Abs(shiftPattern) % alphabet.Length); 
        res = res % alphabet.Length 
        sb.Append(alphabet[res]); 
       } 
       return sb.ToString(); 
      } 
+0

(RES <0)被擊中說-150,我知道它在這個類型的算法不太可能,因爲大多數人將轉移是26,但它在那裏,以防萬一。 – Morn 2011-03-17 09:47:20

+0

好吧,然後我將編輯代碼,向shiftpattern添加一個Math.Abs​​並刪除條件。 – Jonathan 2011-03-17 09:54:33

+0

我也刪除了(res> = 26)檢查。我們可以直接進行模塊操作。無論數字是否大於26。 – Jonathan 2011-03-17 10:01:00

0

我建議以下,

  1. 的情況下,或兩個以上的條件下使用開關 - 案例。
  2. 相反的char []或任何變量聲明使用var的如使用3.0或以上
  3. 對於和使用lambda表達式避免foreach循環。
  4. 使這樣的方法變爲靜態,並將其放在可以全局共享的一些常見類中。

更多好的做法。按照從JetBrains公司

+0

我不確定我是否同意所有這些:1.他沒有進行平等檢查,但 - 您可以切換case> = 26,case <0嗎? 2.國際海事組織最好留下像'char'這樣的基本類型3,但這通常不太易讀,(我認爲)效率稍低一些 - 如果你要返回一個新的集合,但在一般情況下不會。 – Rup 2011-03-17 09:58:39

1

ReSharper的工具,沒有必要保持完整的字母列表。
此外,如果你不支持空格,那麼你的消息將像羅馬拉丁文,沒有空格...

public static string Encrypt(string inputString, int shiftPattern) 
    { 
     StringBuilder sb = new StringBuilder(); 
     foreach(char letter in inputString.ToLower()) 
     { 
      int encryptedValue = 0; 
      if (letter == ' ') 
      { 
       encryptedValue = ' '; 
      } 
      else 
      { 
       encryptedValue = (((letter - 'a') + shiftPattern) % 26) + 'a'; 
      } 

      sb.Append((char)encryptedValue); 
     } 
     return sb.ToString(); 
    } 
+0

+1這 - 唯一的表現擔心,我不得不將'Array.IndexOf'(和使用在foreach'char'不'var'!)。但是我會使用''a''等等,而不是數字常量,並檢查'if((letter> ='A')&&(letter <='Z'))'if((letter> 'a')&&(letter <='z'))'所以你只加密字母,而不是嘗試和加密一切不是空格的東西。在這種情況下使用StringBuilder對我來說也感覺不對,但很多微軟的代碼都這樣做,所以它必須是有效的。 – Rup 2011-03-17 10:04:56

+0

不要使用97,請使用'a'。 – Carra 2011-03-17 12:47:30

0

有了一些改變算法:

static char[] alphabet = { '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' }; 

public static string Encrypt(string inputString, int shiftPattern) 
{ 
    if (inputString == null) return null; 
    if (shiftPattern <= 0) 
    { 
     shiftPattern = alphabet.Length + shiftPattern % alphabet.Length; 
    } 

    var chars = inputString.Select(c => 
    { 
     var index = Array.IndexOf(alphabet, char.ToLower(c)); 
     if (index == -1) return c; 

     var result = alphabet[(index + shiftPattern) % 26]; 
     return char.IsLower(c) ? result : char.ToUpper(result); 
    }); 

    return new string(chars.ToArray()); 
} 
  • 管理空字符串的情況。
  • 非cyphyrable字符保持原狀(在密碼中有爭議...)
  • 只需使用linq而不是舊式循環和構建器。
  • 管理大寫
  • 縮短,同時還可以理解沒有問題。
  • 我分開選擇爲清晰起見,回到這裏,在正常的代碼,如果返回......選擇線路不超過列限制的代碼庫,我會結合兩種走。
+0

所以我很奇怪,爲什麼如果(shiftPattern <= 0)拋出新ArgumentOutOfRangeException( 「shiftPattern」);線。 如果你想能夠轉移negitivly那麼這阻止你沒有?? – Morn 2011-03-17 10:28:44

+0

是的,如果它真的是一個所需的功能而不增加複雜性,它可以被替換爲'shiftPattern = alphabet.Length + shiftPattern%alphabet.Length'。 – 2011-03-17 13:38:40

+0

我剛纔認爲負面轉變並不是很有用。我將修改從負號保持更接近原來的解決方案 – 2011-03-17 13:40:03

1

您可以將數組和所有內容放在for循環中的一行代碼中。

 StringBuilder sb = new StringBuilder(); 
     foreach (var letter in inputString.ToLower()) 
      sb.Append((char)((((letter - 'a') + shiftpattern)%26) + 'a')); 

在:殭屍&移1

日期:apncjf

+0

有趣的工作,每次考試除了像-1轉變 – Morn 2011-03-17 11:16:30

+0

是的,不包括負數。移動-1與完全移動25相同。 – Carra 2011-03-17 12:49:25

+0

好點!!!!! – Morn 2011-03-17 15:00:53