【发布时间】:2018-11-29 04:07:43
【问题描述】:
使用Console.WriteLine(),它会输出:
我希望它自动看起来像这样,而不是在需要的地方手动输入\n:
这可能吗?如果有,怎么做?
【问题讨论】:
标签: c# .net console formatting
使用Console.WriteLine(),它会输出:
我希望它自动看起来像这样,而不是在需要的地方手动输入\n:
这可能吗?如果有,怎么做?
【问题讨论】:
标签: c# .net console formatting
这是一个适用于制表符、换行符和其他空格的解决方案。
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);
}
}
【讨论】:
这将接受一个字符串并返回一个不超过 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.
【讨论】:
foreach(var line in lines) yield return line; 包装到函数中时添加到末尾。
lines。
Aggregate 构建的,它返回一个 LINQ IEnumerable。返回行不仅等效,而且经过优化。
在几分钟内编码,它实际上会被超过 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 和内存上也没有得到很好的优化。我不会在任何严肃的情况下使用它。
【讨论】:
String line = buffer.ToString().Substring(0, buffer.Length - word.Length); 行中
这应该可以工作,尽管它可能可以再缩短一些:
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:我认为它不会取代标签。
【讨论】:
您可以使用 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 是我开发的。
【讨论】:
如果您有一个大于屏幕宽度的单词(如路径),则还需要自动换行。
using System;
using System.Text;
namespace Colorify.Terminal
{
public static class Wrapper
{
static int _screenWidth { get; set; }
public static void Text(string text)
{
StringBuilder line = new StringBuilder();
string[] words = text.Split(' ');
_screenWidth = (Console.WindowWidth - 3);
foreach (var item in words)
{
Line(ref line, item);
Item(ref line, item);
}
if (!String.IsNullOrEmpty(line.ToString().Trim()))
{
Out.WriteLine($"{line.ToString().TrimEnd()}");
}
}
static void Line(ref StringBuilder line, string item)
{
if (
((line.Length + item.Length) >= _screenWidth) ||
(line.ToString().Contains(Environment.NewLine))
)
{
Out.WriteLine($"{line.ToString().TrimEnd()}");
line.Clear();
}
}
static void Item(ref StringBuilder line, string item)
{
if (item.Length >= _screenWidth)
{
if (line.Length > 0)
{
Out.WriteLine($" {line.ToString().TrimEnd()}");
line.Clear();
}
int chunkSize = item.Length - _screenWidth;
string chunk = item.Substring(0, _screenWidth);
line.Append($"{chunk} ");
Line(ref line, item);
item = item.Substring(_screenWidth, chunkSize);
Item(ref line, item);
}
else
{
line.Append($"{item} ");
}
}
}
}
它已在 Colorify 上实现 - 具有文本格式的 C# NETCore 控制台库:颜色、对齐方式等等 [适用于 Win、Mac 和 Linux]
【讨论】:
您应该能够利用 Console.WindowWidth 和一些前瞻换行逻辑来实现这一点。
【讨论】:
Console.BufferWidth 可能是更好的选择,具体取决于您要实现的目标。