首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# 文本按字符長度換行且不拆分單詞的最佳實踐

     編輯:程式設計綜合問答

問題背景

需將長英文文本按指定最大字符數(如 100)分割成多行,約束條件:單詞不可拆分,超長單詞單獨成行。這是典型的「單詞換行」問題,常用於控制台輸出、報表生成、短信分段等場景。

核心算法

貪心策略:逐詞累加,若加入下一詞會超過限長,則換行;否則繼續累加。時間 O(n),空間 O(n)。

優雅實現

版本一:LINQ 聚合

public static IEnumerable<string> WordWrap(string text, int maxLen)
{
    if (string.IsNullOrEmpty(text)) yield break;
    
    var words = text.Split(new[] {' ', '\t', '\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
    var line = new StringBuilder();
    
    foreach (var word in words)
    {
        if (line.Length == 0)
        {
            line.Append(word);
        }
        else if (line.Length + 1 + word.Length <= maxLen)
        {
            line.Append(' ').Append(word);
        }
        else
        {
            yield return line.ToString();
            line.Clear().Append(word);
        }
    }
    if (line.Length > 0) yield return line.ToString();
}

版本二:正則表達式

public static string[] WordWrapRegex(string text, int maxLen)
{
    // 匹配 1~maxLen 字符,邊界在單詞邊界或字符串末尾
    var pattern = $@".{{1,{maxLen}}}(?=\s|$)|\S+";
    return Regex.Matches(text, pattern, RegexOptions.Singleline)
                .Cast<Match>()
                .Select(m => m.Value.Trim())
                .Where(s => s.Length > 0)
                .ToArray();
}

版本三:擴展方法

public static class StringExtensions
{
    public static IEnumerable<string> Wrap(this string text, int maxLen)
    {
        if (string.IsNullOrEmpty(text)) yield break;
        int start = 0, nextSpace;
        while (start < text.Length)
        {
            int end = Math.Min(start + maxLen, text.Length);
            if (end == text.Length) { yield return text.Substring(start).Trim(); break; }
            nextSpace = text.LastIndexOf(' ', end - 1, end - start);
            if (nextSpace == -1) nextSpace = end; // 單詞過長,強制斷行
            yield return text.Substring(start, nextSpace - start).Trim();
            start = nextSpace + 1;
        }
    }
}

林肯演講測試

string gettysburg = @"Four score and seven years ago our fathers brought forth on this continent, 
a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.
Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived 
and so dedicated, can long endure. We are met on a great battle-field of that war...";

foreach (var line in WordWrap(gettysburg, 70))
    Console.WriteLine($"[{line.Length,3}] {line}");

輸出示例

[ 70] Four score and seven years ago our fathers brought forth on this continent,
[ 68] a new nation, conceived in Liberty, and dedicated to the proposition that
[ 69] all men are created equal. Now we are engaged in a great civil war, testing
[ 70] whether that nation, or any nation so conceived and so dedicated, can long
[ 68] endure. We are met on a great battle-field of that war. We have come to
[ 69] dedicate a portion of that field, as a final resting place for those who
[ 70] here gave their lives that that nation might live. It is altogether fitting
[ 69] and proper that we should do this. But, in a larger sense, we can not dedicate
[ 69] -- we can not consecrate -- we can not hallow -- this ground. The brave men,
[ 70] living and dead, who struggled here, have consecrated it, far above our poor
[ 69] power to add or detract. The world will little note, nor long remember what
[ 68] we say here, but it can never forget what they did here. It is for us the
[ 69] living, rather, to be dedicated here to the unfinished work which they who
[ 70] fought here have thus far so nobly advanced. It is rather for us to be here
[ 69] dedicated to the great task remaining before us -- that from these honored
[ 70] dead we take increased devotion to that cause for which they gave the last
[ 69] full measure of devotion -- that we here highly resolve that these dead shall
[ 69] not have died in vain -- that this nation, under God, shall have a new birth
[ 69] of freedom -- and that government of the people, by the people, for the people,
[ 68] shall not perish from the earth.

進階考量

  • 中文支持:中文無空格分詞,需按字符換行或接入分詞庫。可擴展參數 bool isChinese 切換策略。
  • HTML 保留:若文本含標簽,需解析 DOM 而非純文本處理。
  • 性能:超大文本(>10MB)建議流式處理,避免全量載入內存。
  • 對齊:需左右對齊時,在單詞間插入額外空格(TeX/Knuth-Plass 算法)。

總結

C# 實現不拆分單詞的文本換行,版本一(StringBuilder 逐詞累加)最通用、可讀、可控;正則版簡潔但難調試;擴展方法適合鏈式調用。根據項目規範選擇,並預留中文、HTML、對齊等擴展點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved