我有一种列显示,但最后两列似乎没有正确对齐。这是我目前的代码:
Console.WriteLine("Customer name "
+ "sales "
+ "fee to be paid "
+ "70% value "
+ "30% value");
for (int DisplayPos = 0; DisplayPos < LineNum; DisplayPos = DisplayPos + 1)
{
seventy_percent_value = ((fee_payable[DisplayPos] / 10.0) * 7);
thirty_percent_value = ((fee_payable[DisplayPos] / 10.0) * 3);
Console.WriteLine(customer[DisplayPos] + " "
+ sales_figures[DisplayPos] + " "
+ fee_payable[DisplayPos] + " "
+ seventy_percent_value + " "
+ thirty_percent_value);
}
我是一名菜鸟程序员,所以我可能不理解所有的建议,但如果您有任何建议,我们将不胜感激!
答案 0 :(得分:274)
试试这个
Console.WriteLine("{0,10}{1,10}{2,10}{3,10}{4,10}",
customer[DisplayPos],
sales_figures[DisplayPos],
fee_payable[DisplayPos],
seventy_percent_value,
thirty_percent_value);
其中大括号内的第一个数字是索引,第二个是对齐。第二个数字的符号表示字符串是左对齐还是右对齐。使用负数进行左对齐。
或者看看 http://msdn.microsoft.com/en-us/library/aa331875(v=vs.71).aspx
答案 1 :(得分:43)
只是为了添加roya的答案。在c#6.0中,您现在可以使用字符串插值:
Console.WriteLine($"{customer[DisplayPos],10}" +
$"{salesFigures[DisplayPos],10}" +
$"{feePayable[DisplayPos],10}" +
$"{seventyPercentValue,10}" +
$"{thirtyPercentValue,10}");
这实际上可以是没有所有额外资金的一行,我只是认为这样可以更容易阅读。
你也可以在System.Console上使用静态导入,允许你这样做:
using static System.Console;
WriteLine(/* write stuff */);
答案 2 :(得分:12)
您应该将实际标签(\t
转义序列)嵌入到每个输出字符串中,而不是尝试将文本手动对齐到具有任意空格字符串的列中:
Console.WriteLine("Customer name" + "\t"
+ "sales" + "\t"
+ "fee to be paid" + "\t"
+ "70% value" + "\t"
+ "30% value");
for (int DisplayPos = 0; DisplayPos < LineNum; DisplayPos++)
{
seventy_percent_value = ((fee_payable[DisplayPos] / 10.0) * 7);
thirty_percent_value = ((fee_payable[DisplayPos] / 10.0) * 3);
Console.WriteLine(customer[DisplayPos] + "\t"
+ sales_figures[DisplayPos] + "\t"
+ fee_payable + "\t\t"
+ seventy_percent_value + "\t\t"
+ thirty_percent_value);
}
答案 3 :(得分:6)
我知道,很老的线程,但是当有更长的字符串时,建议的解决方案并不是完全自动的。
因此我创建了一个小辅助方法,它完全自动化。只需传入一个字符串数组列表,其中每个数组代表一行和数组中的每个元素,以及该行的元素。
该方法可以这样使用:
var lines = new List<string[]>();
lines.Add(new[] { "What", "Before", "After"});
lines.Add(new[] { "Name:", name1, name2});
lines.Add(new[] { "City:", city1, city2});
lines.Add(new[] { "Zip:", zip1, zip2});
lines.Add(new[] { "Street:", street1, street2});
var output = ConsoleUtility.PadElementsInLines(lines, 3);
辅助方法如下:
public static class ConsoleUtility
{
/// <summary>
/// Converts a List of string arrays to a string where each element in each line is correctly padded.
/// Make sure that each array contains the same amount of elements!
/// - Example without:
/// Title Name Street
/// Mr. Roman Sesamstreet
/// Mrs. Claudia Abbey Road
/// - Example with:
/// Title Name Street
/// Mr. Roman Sesamstreet
/// Mrs. Claudia Abbey Road
/// <param name="lines">List lines, where each line is an array of elements for that line.</param>
/// <param name="padding">Additional padding between each element (default = 1)</param>
/// </summary>
public static string PadElementsInLines(List<string[]> lines, int padding = 1)
{
// Calculate maximum numbers for each element accross all lines
var numElements = lines[0].Length;
var maxValues = new int[numElements];
for (int i = 0; i < numElements; i++)
{
maxValues[i] = lines.Max(x => x[i].Length) + padding;
}
var sb = new StringBuilder();
// Build the output
bool isFirst = true;
foreach (var line in lines)
{
if (!isFirst)
{
sb.AppendLine();
}
isFirst = false;
for (int i = 0; i < line.Length; i++)
{
var value = line[i];
// Append the value with padding of the maximum length of any value for this element
sb.Append(value.PadRight(maxValues[i]));
}
}
return sb.ToString();
}
}
希望这有助于某人。来源是我博客上的帖子:http://dev.flauschig.ch/wordpress/?p=387
答案 4 :(得分:2)
您可以在列之间使用制表符而不是空格,和/或为格式字符串中的列设置最大大小...
答案 5 :(得分:2)
有几个NuGet包可以帮助格式化。在某些情况下,string.Format
的功能已足够,但您可能希望至少根据内容自动调整列的大小。
ConsoleTableExt是一个简单的库,它允许格式化表格,包括没有网格线的表格。 (一个更受欢迎的包ConsoleTables似乎不支持无边界表。)这是一个格式化对象列表的示例,其中列的大小基于其内容:
ConsoleTableBuilder
.From(orders
.Select(o => new object[] {
o.CustomerName,
o.Sales,
o.Fee,
o.Value70,
o.Value30
})
.ToList())
.WithColumn(
"Customer",
"Sales",
"Fee",
"70% value",
"30% value")
.WithFormat(ConsoleTableBuilderFormat.Minimal)
.WithOptions(new ConsoleTableBuilderOption { DividerString = "" })
.ExportAndWriteLine();
如果您需要更多功能,可以使用CsConsoleFormat实现任何控制台格式化。†例如,这里将对象列表格式化为固定列宽为10的网格,就像在其他答案中一样使用string.Format
:
ConsoleRenderer.RenderDocument(
new Document { Color = ConsoleColor.Gray }
.AddChildren(
new Grid { Stroke = LineThickness.None }
.AddColumns(10, 10, 10, 10, 10)
.AddChildren(
new Div("Customer"),
new Div("Sales"),
new Div("Fee"),
new Div("70% value"),
new Div("30% value"),
orders.Select(o => new object[] {
new Div().AddChildren(o.CustomerName),
new Div().AddChildren(o.Sales),
new Div().AddChildren(o.Fee),
new Div().AddChildren(o.Value70),
new Div().AddChildren(o.Value30)
})
)
));
它可能看起来比纯string.Format
更复杂,但现在它可以自定义。例如:
如果您想根据内容自动调整列数,请将AddColumns(10, 10, 10, 10, 10)
替换为AddColumns(-1, -1, -1, -1, -1)
(-1
是GridLength.Auto
的快捷方式,您有更多尺寸选项,包括控制台窗口宽度的百分比。
如果您想将数字列对齐,请将{ Align = Right }
添加到单元格的初始化程序中。
如果要为列着色,请将{ Color = Yellow }
添加到单元格的初始值设定项中。
您可以更改边框样式等。
†CsConsoleFormat由我开发。
答案 6 :(得分:0)
我真的很喜欢这里提到的那些库,但我有一个想法,可能比填充或做大量的字符串操作更简单,
您可以使用数据的最大字符串长度手动设置光标。这里有一些代码可以获得想法(未经测试):
var column1[] = {"test", "longer test", "etc"}
var column2[] = {"data", "more data", "etc"}
var offset = strings.OrderByDescending(s => s.Length).First().Length;
for (var i = 0; i < column.Length; i++) {
Console.Write(column[i]);
Console.CursorLeft = offset + 1;
Console.WriteLine(column2[i]);
}
如果你有更多的行,你可以很容易地推断出来。
答案 7 :(得分:0)
做一些填充,即
public static void prn(string fname, string fvalue)
{
string outstring = fname.PadRight(20) +"\t\t " + fvalue;
Console.WriteLine(outstring);
}
这很好,至少对我而言。