需將長英文文本按指定最大字符數(如 100)分割成多行,約束條件:單詞不可拆分,超長單詞單獨成行。這是典型的「單詞換行」問題,常用於控制台輸出、報表生成、短信分段等場景。
貪心策略:逐詞累加,若加入下一詞會超過限長,則換行;否則繼續累加。時間 O(n),空間 O(n)。
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 切換策略。C# 實現不拆分單詞的文本換行,版本一(StringBuilder 逐詞累加)最通用、可讀、可控;正則版簡潔但難調試;擴展方法適合鏈式調用。根據項目規範選擇,並預留中文、HTML、對齊等擴展點。