web-dev-qa-db-ja.com

Console.WriteLineを使用して列内のテキストを整列するにはどうすればよいですか?

ある種の列表示がありますが、最後の2列は正しく位置合わせされていないようです。これは私が現在持っているコードです:

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);
}

私は新人プログラマーなので、与えられたすべてのアドバイスを理解できないかもしれませんが、何かアドバイスがあれば大歓迎です!

74
Stephen Smith

テキストを手動でスペースの任意の文字列を持つ列に配置しようとする代わりに、実際のタブ(\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);
}
12
Cody Gray

これを試して

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);

ここで、中括弧内の最初の数値はインデックスで、2番目の数値は配置です。 2番目の数字の符号は、文字列を左揃えにするか右揃えにするかを示します。左揃えには負の数を使用します。

または http://msdn.Microsoft.com/en-us/library/aa331875(v = vs.71).aspx をご覧ください

282
royas

ロヤの答えに追加するだけです。 C#6.0では、文字列補間を使用できるようになりました。

Console.WriteLine($"{customer[DisplayPos],10}" +
                  $"{salesFigures[DisplayPos],10}" +
                  $"{feePayable[DisplayPos],10}" +
                  $"{seventyPercentValue,10}" +
                  $"{thirtyPercentValue,10}");

これは、実際には余分なお金を一切使わずに1行にすることができます。このように読むと少し簡単になると思います。

また、System.Consoleで静的インポートを使用して、これを行うこともできます。

using static System.Console;

WriteLine(/* write stuff */);
45
Daniel Hakimi

非常に古いスレッドを知っていますが、提案されたソリューションは、周囲に長い文字列がある場合、完全に自動化されていませんでした。

したがって、完全に自動化する小さなヘルパーメソッドを作成しました。文字列配列のリストを渡すだけで、各配列は行を表し、配列内の各要素は行の要素を表します。

メソッドは次のように使用できます。

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

7
Roemer

フォーマットに役立つNuGetパッケージがいくつかあります。場合によってはstring.Formatの機能で十分ですが、少なくともコンテンツに基づいて列のサイズを自動調整することができます。

ConsoleTableExt

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

それよりも多くの機能が必要な場合、コンソールのフォーマットは 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)に置き換えます(-1GridLength.Autoへのショートカットです。コンソールの割合など、より多くのサイズ設定オプションがあります。ウィンドウの幅)。

  • 数値列を右に揃える場合は、{ Align = Right }をセルの初期化子に追加します。

  • 列に色を付ける場合は、{ Color = Yellow }をセルの初期化子に追加します。

  • 境界線のスタイルなどを変更できます。

†CsConsoleFormatは私が開発しました。

2
Athari

列間のスペースの代わりにタブを使用したり、フォーマット文字列で列の最大サイズを設定したりできます...

2
LaGrandMere

私はここで言及したライブラリが本当に好きですが、ただパディングしたり、大量の文字列操作をしたりするよりも簡単なアイデアがありました。

データの最大文字列長を使用して、手動でカーソルを設定できます。アイデアを得るためのコードを次に示します(テストされていません):

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]);
}

より多くの行がある場合、簡単に推定できます。

1
Sauleil