将长字符串分成60个字符的长行,但不要破坏单词

必须有一个更好的方法来做到这一点。 我只想将长字符串分成60个字符行,但不要破坏单词。 因此,它不必添加多达60个字符,只需要小于60。

下面的代码是我所拥有的并且它有效,但我认为有更好的方法。 任何人?

修改为使用StringBuilder并修复了删除重复单词的问题。 也不想使用正则表达式,因为我认为这将比我现在的效率低。

public static List FormatMe(String Message) { Int32 MAX_WIDTH = 60; List Line = new List(); String[] Words; Message = Message.Trim(); Words = Message.Split(" ".ToCharArray()); StringBuilder s = new StringBuilder(); foreach (String Word in Words) { s.Append(Word + " "); if (s.Length > MAX_WIDTH) { s.Replace(Word, "", 0, s.Length - Word.Length); Line.Add(s.ToString().Trim()); s = new StringBuilder(Word + " "); } } if (s.Length > 0) Line.Add(s.ToString().Trim()); return Line; } 

谢谢

试试这个:

 const Int32 MAX_WIDTH = 60; string text = "..."; List lines = new List(); StringBuilder line = new StringBuilder(); foreach(Match word in Regex.Matches(text, @"\S+", RegexOptions.ECMAScript)) { if (word.Value.Length + line.Length + 1 > MAX_WIDTH) { lines.Add(line.ToString()); line.Length = 0; } line.Append(String.Format("{0} ", word.Value)); } if (line.Length > 0) line.Append(word.Value); 

请检查一下: 如何使用正则表达式添加换行符?

另一个(现在测试)样本,与Keith方法非常相似:

 static void Main(string[] args) { const Int32 MAX_WIDTH = 60; int offset = 0; string text = Regex.Replace(File.ReadAllText("oneline.txt"), @"\s{2,}", " "); List lines = new List(); while (offset < text.Length) { int index = text.LastIndexOf(" ", Math.Min(text.Length, offset + MAX_WIDTH)); string line = text.Substring(offset, (index - offset <= 0 ? text.Length : index) - offset ); offset += line.Length + 1; lines.Add(line); } } 

我在这个文件上运行它,所有换行符都被“”替换。

在正则表达式中,Match Evaluator函数(一个匿名方法)执行grunt工作并将新大小的行存储到StringBuilder中。 我们不使用Regex.Replace方法的返回值,因为我们只是使用它的Match Evaluator函数作为一个特性来完成正则表达式调用内部的换行 – 只是为了它,因为我认为它很酷。

 using System; using System.Text; using System.Text.RegularExpressions; 

strInput是你想要转换的行。

 int MAX_LEN = 60; StringBuilder sb = new StringBuilder(); int bmark = 0; //bookmark position Regex.Replace(strInput, @".*?\b\w+\b.*?", delegate(Match m) { if (m.Index - bmark + m.Length + m.NextMatch().Length > MAX_LEN || m.Index == bmark && m.Length >= MAX_LEN) { sb.Append(strInput.Substring(bmark, m.Index - bmark + m.Length).Trim() + Environment.NewLine); bmark = m.Index + m.Length; } return null; }, RegexOptions.Singleline); if (bmark != strInput.Length) // last portion sb.Append(strInput.Substring(bmark)); string strModified = sb.ToString(); // get the real string from builder 

还有值得注意的是匹配评估m.Index == bmark && m.Length >= MAX_LEN if表达式中的第二个条件m.Index == bmark && m.Length >= MAX_LEN是一个exception条件,以防有一个字长于60个字符(或长于该字符集)最大长度) – 它不会在这里被分解,而是仅仅存储在一条线上 – 我想你可能想要在现实世界中为该条件创建第二个公式以连接它或其他东西。

我将从保存原始字符串的长度开始。 然后,向后开始,然后减去,因为我可以通过从最后一个单词开始然后返回而不是构建来获得低于60的可能性。

一旦我知道了多长时间,那么只需使用StringBuilder并为新字符串构建字符串。

 List lines = new List(); while (message.Length > 60) { int idx = message.LastIndexOf(' ', 60); lines.Add(message.Substring(0, idx)); message = message.Substring(idx + 1, message.Length - (idx + 1)); } lines.Add(message); 

您可能需要修改一个位来处理多个空格,其中包含> 60个字符的单词,…

另一个 …

 public static string SplitLongWords(string text, int maxWordLength) { var reg = new Regex(@"\S{" + (maxWordLength + 1) + ",}"); bool replaced; do { replaced = false; text = reg.Replace(text, (m) => { replaced = true; return m.Value.Insert(maxWordLength, " "); }); } while (replaced); return text; } 

我尝试了原始解决方案,发现它不太有效。 我稍微修改了它以使其工作。 它现在适用于我并解决了我遇到的问题。 谢谢。 吉姆。

 public static List FormatMe(String message) { int maxLength = 10; List Line = new List(); String[] words; message = message.Trim(); words = message.Split(" ".ToCharArray()); StringBuilder sentence = new StringBuilder(); foreach (String word in words) { if((sentence.Length + word.Length) <= maxLength) { sentence.Append(word + " "); } else { Line.Add(sentence.ToString().Trim()); sentence = new StringBuilder(word + " "); } } if (sentence.Length > 0) Line.Add(sentence.ToString().Trim()); return Line; } private void btnSplitText_Click(object sender, EventArgs e) { List Line = new List(); string message = "The quick brown fox jumps over the lazy dog."; Line = FormatMe(message); }