2013-03-08 35 views
7

我有一個很長的字符串,我想將它放在一個小的字段中。爲了實現這一點,我把字符串分成空白行。算法如下:將文本分割成最大長度的線條

public static string BreakLine(string text, int maxCharsInLine) 
    { 
     int charsInLine = 0; 
     StringBuilder builder = new StringBuilder(); 
     for (int i = 0; i < text.Length; i++) 
     { 
      char c = text[i]; 
      builder.Append(c); 
      charsInLine++; 

      if (charsInLine >= maxCharsInLine && char.IsWhiteSpace(c)) 
      { 
       builder.AppendLine(); 
       charsInLine = 0; 
      } 
     } 
     return builder.ToString(); 
    } 

但是,如果有一個短的單詞,然後是一個較長的單詞,這會中斷。最大長度爲16的「foo howcomputerwork」不會中斷,但我希望這樣做。我以爲有一個想法是期待看到下一個空白出現在哪裏,但我不確定這是否會導致儘可能少的行數。

+0

你想*至少* n個字符在一行或*最多*?因爲如果你想*最多* n個字符,你需要從第n個字符回到空白字符。如果任何時候有超過n個字符的單詞,那麼你就被搞砸了。^_ ^; – Corak 2013-03-08 12:54:56

+0

@Corak「將文本分割成最大**長度的行」,這並不意味着*最多*? – Nolonar 2013-03-08 12:56:32

+0

@Nolonar是的,但代碼暗示*至少*,所以我不確定。 – Corak 2013-03-08 12:58:08

回答

1

檢查字符的內容寫入字符串生成器之前,並與當前計數or它:

public static string BreakLine(string text, int maxCharsInLine) 
    { 
     int charsInLine = 0; 
     StringBuilder builder = new StringBuilder(); 
     for (int i = 0; i < text.Length; i++) 
     { 
      char c = text[i]; 
      if (char.IsWhiteSpace(c) || charsInLine >= maxCharsInLine) 
      { 
       builder.AppendLine(); 
       charsInLine = 0; 
      } 
      else 
      { 
       builder.Append(c); 
       charsInLine++;      
      } 
     } 
     return builder.ToString(); 
    } 
+0

大量使用字符串生成器,在將這些字符串合併在一起時,它是必需的。看起來它會爲文本中的每個單詞添加一個新行。 – 2014-09-10 13:37:26

+0

此代碼將每個單詞放在新行中,而不管行尾(基於maxCharsInLine)還是不行。 – 2014-10-03 12:10:58

+0

@PR根據被問到的問題:'我將字符串拆分爲空白行'意味着他在空白處(和字符數)打破了排隊 – Moop 2014-10-03 16:53:55

6

享受!

public static string SplitToLines(string text, char[] splitOnCharacters, int maxStringLength) 
{ 
    var sb = new StringBuilder(); 
    var index = 0; 

    while (text.Length > index) 
    { 
     // start a new line, unless we've just started 
     if (index != 0) 
      sb.AppendLine(); 

     // get the next substring, else the rest of the string if remainder is shorter than `maxStringLength` 
     var splitAt = index + maxStringLength <= text.Length 
      ? text.Substring(index, maxStringLength).LastIndexOfAny(splitOnCharacters) 
      : text.Length - index; 

     // if can't find split location, take `maxStringLength` characters 
     splitAt = (splitAt == -1) ? maxStringLength : splitAt; 

     // add result to collection & increment index 
     sb.Append(text.Substring(index, splitAt).Trim()); 
     index += splitAt; 
    } 

    return sb.ToString(); 
} 

注意splitOnCharactersmaxStringLength可以保存在應用程序的用戶設置區域。

+0

Original Post已經過測試和工作,不確定@DIMI是否有機會測試他/她的編輯,但是我有感覺IIRC(從2年前= P),您需要使用此方法在每行注入1個字符。 – 2016-02-25 14:20:45

+1

嘿:)我使用相同的代碼。我只是將它實現爲一個擴展,因爲它是分裂到數組或分裂成行的最流行的用法。你的回答很好,所以我做了+1,男人。 – 2016-02-25 14:56:32

0

稍微更新了一段代碼,@ dead.rabit有時會循環。

public static string SplitToLines(string text,char[] splitanyOf, int maxStringLength) 
    {    
     var sb = new System.Text.StringBuilder(); 
     var index = 0; 
     var loop = 0; 
     while (text.Length > index) 
     { 
      // start a new line, unless we've just started 
      if (loop != 0) 
      { 
       sb.AppendLine(); 
      } 

      // get the next substring, else the rest of the string if remainder is shorter than `maxStringLength` 
      var splitAt = 0; 
      if (index + maxStringLength <= text.Length) 
      { 
       splitAt = text.Substring(index, maxStringLength).LastIndexOfAny(splitanyOf); 
      } 
      else 
      { 
       splitAt = text.Length - index; 
      } 

      // if can't find split location, take `maxStringLength` characters 
      if (splitAt == -1 || splitAt == 0) 
      { 
       splitAt = text.IndexOfAny(splitanyOf, maxStringLength); 
      } 

      // add result to collection & increment index 
      sb.Append(text.Substring(index, splitAt).Trim()); 
      if(text.Length > splitAt) 
      { 
       text = text.Substring(splitAt + 1).Trim(); 
      } 
      else 
      { 
       text = string.Empty; 
      } 
      loop = loop + 1; 
     } 

     return sb.ToString(); 
    }