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

时间:2009-11-05 02:57:24

标签: c# .net string

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

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

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

public static List<String> FormatMe(String Message)
{
    Int32 MAX_WIDTH = 60;
    List<String> Line = new List<String>();
    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;
}

由于

7 个答案:

答案 0 :(得分:6)

另一个(现在为TESTED)样本,与Keith approach非常相似:

static void Main(string[] args)
{
    const Int32 MAX_WIDTH = 60;

    int offset = 0;
    string text = Regex.Replace(File.ReadAllText("oneline.txt"), @"\s{2,}", " ");
    List<string> lines = new List<string>();
    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);
    }
}

我在this file上运行它,所有换行符都被“”替换为。“。

答案 1 :(得分:1)

在正则表达式中,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表达式中的第二个条件是一个异常条件,以防有一个字长于60个字符(或长于设置的最大长度) - 它不会在这里分解,而只是单独存储在一行上 - 我想你可能想在现实世界中创建第二个公式来连接它或其他东西。

答案 2 :(得分:0)

试试这个:

const Int32 MAX_WIDTH = 60;

string text = "...";
List<string> lines = new List<string>();
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);

请同时查看:How do I use a regular expression to add linefeeds?

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

List<string> lines = new List<string>();
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);

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

答案 5 :(得分:0)

另一个......

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;
}

答案 6 :(得分:0)

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

body {
  /* Workaround for some mobile browsers */
  background: url('bg.jpg') no-repeat center center;
  background-size: cover;
  min-height: 100vh;
  padding-top: 20px;
  padding-bottom: 20px;
}