2013-12-12 19 views

回答

0

這應該工作,但大概可以縮短些:

public static void WordWrap(string paragraph) 
    { 
     paragraph = new Regex(@" {2,}").Replace(paragraph.Trim(), @" "); 
     var left = Console.CursorLeft; var top = Console.CursorTop; var lines = new List<string>(); 
     for (var i = 0; paragraph.Length > 0; i++) 
     { 
      lines.Add(paragraph.Substring(0, Math.Min(Console.WindowWidth, paragraph.Length))); 
      var length = lines[i].LastIndexOf(" ", StringComparison.Ordinal); 
      if (length > 0) lines[i] = lines[i].Remove(length); 
      paragraph = paragraph.Substring(Math.Min(lines[i].Length + 1, paragraph.Length)); 
      Console.SetCursorPosition(left, top + i); Console.WriteLine(lines[i]); 
     } 
    } 

這可能是很難理解,所以基本上這是什麼一樣:

Trim()在開始和結束時刪除空格。
Regex()用一個空格替換多個空格。
for循環取段落中的第一個(Console.WindowWidth - 1)字符並將其設置爲新行。
'LastIndexOf()1嘗試查找行中的最後一個空格。如果沒有,它會保持原樣。
該行從段落中刪除,循環重複。

注:該正則表達式取自here。注2:我不認爲它會取代標籤。

+1

有新行時會發生什麼?爲什麼要修剪空白並替換多個空格?多個空間可用於跨多行佈局內容。 – roydukkey

-1

你或許應該能夠利用Console.WindowWidth一些先行換行符的邏輯來實現這一目標。

+0

「Console.BufferWidth」可能是更好的選擇,具體取決於您嘗試實現的目標。 –

2

在一兩分鐘的編碼,它實際上與擁有超過80個字符,並沒有考慮到Console.WindowWidth

private static void EpicWriteLine(String text) 
{ 
    String[] words = text.Split(' '); 
    StringBuilder buffer = new StringBuilder(); 

    foreach (String word in words) 
    { 
    buffer.Append(word); 

    if (buffer.Length >= 80) 
    { 
     String line = buffer.ToString().Substring(0, buffer.Length - word.Length); 
     Console.WriteLine(line); 
     buffer.Clear(); 
     buffer.Append(word); 
    } 

    buffer.Append(" "); 

    } 

    Console.WriteLine(buffer.ToString()); 
} 

它也不能同時CPU和內存上非常優化的話打破。我不會在任何嚴肅的情況下使用它。

+0

它給出了一個StackOverflow異常。發生在行'String line = buffer.ToString()。子字符串(0,buffer.Length - word.Length);' – Frank

2

這將需要一個字符串,並返回一個字符串每次不超過80個字符的列表):

var words = text.Split(' '); 
var lines = words.Skip(1).Aggregate(words.Take(1).ToList(), (l, w) => 
{ 
    if (l.Last().Length + w.Length >= 80) 
     l.Add(w); 
    else 
     l[l.Count - 1] += " " + w; 
    return l; 
}); 

這個text開始:

var text = "Hundreds of South Australians will come out to cosplay when Oz Comic Con hits town this weekend with guest stars including the actor who played Freddy Krueger (A Nightmare on Elm Street) and others from shows such as Game of Thrones and Buffy the Vampire Slayer."; 

我得到這樣的結果:

Hundreds of South Australians will come out to cosplay when Oz Comic Con hits 
town this weekend with guest stars including the actor who played Freddy Krueger 
(A Nightmare on Elm Street) and others from shows such as Game of Thrones and 
Buffy the Vampire Slayer. 
+0

添加了'foreach(var line in lines)yield return line;'將其封裝到一個函數中時結束。 –

+2

@ Dead.Rabit,爲什麼?你也可以直接返回'lines'。 –

+2

@SimonMᶜKenzie你是對的,我收回!行是使用'Aggregate'構建的,它返回一個LINQ IEnumerable。返回線不僅僅是等價的,它稍微更加優化。 –

3

下面是一個解決方案,可以使用製表符,換行符和其他空格。

using System; 
using System.Collections.Generic; 

/// <summary> 
///  Writes the specified data, followed by the current line terminator, to the standard output stream, while wrapping lines that would otherwise break words. 
/// </summary> 
/// <param name="paragraph">The value to write.</param> 
/// <param name="tabSize">The value that indicates the column width of tab characters.</param> 
public static void WriteLineWordWrap(string paragraph, int tabSize = 8) 
{ 
    string[] lines = paragraph 
     .Replace("\t", new String(' ', tabSize)) 
     .Split(new string[] { Environment.NewLine }, StringSplitOptions.None); 

    for (int i = 0; i < lines.Length; i++) { 
     string process = lines[i]; 
     List<String> wrapped = new List<string>(); 

     while (process.Length > Console.WindowWidth) { 
      int wrapAt = process.LastIndexOf(' ', Math.Min(Console.WindowWidth - 1, process.Length)); 
      if (wrapAt <= 0) break; 

      wrapped.Add(process.Substring(0, wrapAt)); 
      process = process.Remove(0, wrapAt + 1); 
     } 

     foreach (string wrap in wrapped) { 
      Console.WriteLine(wrap); 
     } 

     Console.WriteLine(process); 
    } 
} 
0

您可以使用CsConsoleFormat†寫串詞與包裹安慰。它實際上是默認的文本換行模式(但可以改爲字符換行或不換行)。

var doc = new Document().AddChildren(
    "2. I have bugtested this quite a bit however if something " 
    + "goes wrong and the program crashes just restart it." 
); 
ConsoleRenderer.RenderDocument(doc); 

你也可以有保證金的實際列表編號:

var docList = new Document().AddChildren(
    new List().AddChildren(
     new Div("I have not bugtested this enough so if something " 
      + "goes wrong and the program crashes good luck with it."), 
     new Div("I have bugtested this quite a bit however if something " 
      + "goes wrong and the program crashes just restart it.") 
    ) 
); 
ConsoleRenderer.RenderDocument(docList); 

這裏是什麼樣子:

†CsConsoleFormat被我開發的。

相關問題