Wie kann ich Text in Spalten mit Console.WriteLine ausrichten?

77

Ich habe eine Art Spaltenanzeige, aber die beiden letzten Spalten scheinen nicht richtig ausgerichtet zu sein. Dies ist der Code, den ich im Moment habe:

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

Ich bin ein Rookie-Programmierer, daher verstehe ich möglicherweise nicht alle Ratschläge, aber wenn Sie einen Rat haben, wäre er sehr dankbar!

Stephen Smith
quelle
1
Sehen Sie hier für eine verallgemeinerte Version dieser Frage. Die Antworten dort sind ebenfalls einen Blick wert.
Adam Glauser

Antworten:

12

Anstatt zu versuchen, den Text manuell in Spalten mit beliebigen Leerzeichenfolgen auszurichten, sollten Sie tatsächliche Registerkarten (die \tEscape-Sequenz) in jede Ausgabezeichenfolge einbetten :

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);
}
Cody Grey
quelle
37
Registerkarten funktionieren nur dann gut, wenn Ihre Daten alle eine ähnliche Länge haben. Wenn Sie Daten unterschiedlicher Länge haben, sollten Sie royas answer mit Formatzeichenfolgen verwenden.
Tim
3
Ja, das ist eine viel bessere Antwort. Ich habe es positiv bewertet, sobald ich es gesehen habe, aber meins verlassen, nur für den Fall, dass der einfachere Ansatz effektiver wäre. Ich bin mir nicht sicher, warum meine akzeptiert wurde ... :-)
Cody Gray
1
Und vergessen Sie nicht string.PadRight () und string.PadLeft ()
nhershy
Die Antwort von royas ist nicht hilfreich, wenn Sie versuchen, Text mit einer variablen Schriftbreite auszurichten. Ich denke, Sie müssen eine Kombination aus Polsterung mit Registerkarten wie in dieser Antwort verwenden .
Sean
314

Versuche dies

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

Dabei ist die erste Zahl in den geschweiften Klammern der Index und die zweite die Ausrichtung. Das Vorzeichen der zweiten Zahl gibt an, ob die Zeichenfolge links oder rechts ausgerichtet sein soll. Verwenden Sie negative Zahlen für die linke Ausrichtung.

Oder schauen Sie unter http://msdn.microsoft.com/en-us/library/aa331875(v=vs.71).aspx nach

Royas
quelle
18
Tatsächlich müssen Sie die Methode string.format nicht übergeben. Mit anderen Worten, es wird dasselbe sein: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);
Tono Nam
61

Nur um Royas Antwort zu ergänzen. In c # 6.0 können Sie jetzt die Zeichenfolgeninterpolation verwenden:

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

Dies kann tatsächlich eine Zeile ohne all die zusätzlichen Dollars sein. Ich denke nur, dass es ein bisschen einfacher ist, so zu lesen.

Sie können auch einen statischen Import in System.Console verwenden, um Folgendes zu tun:

using static System.Console;

WriteLine(/* write stuff */);
Daniel Hakimi
quelle
4
msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx enthält eine Dokumentation zur "Ausrichtung". Sehr hilfreich!
Frison Alexander
4
Um es links auszurichten, verwenden Sie einfach eine negative Zahl wie folgt : $"{thirtyPercentValue,-10}".
Stomtech
7

Ich weiß, sehr alter Thread, aber die vorgeschlagene Lösung war nicht vollautomatisch, wenn längere Zeichenfolgen vorhanden sind.

Ich habe daher eine kleine Hilfsmethode erstellt, die vollautomatisch funktioniert. Übergeben Sie einfach eine Liste von String-Arrays, in denen jedes Array eine Linie und jedes Element im Array darstellt, also ein Element der Linie.

Die Methode kann folgendermaßen verwendet werden:

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

Die Hilfsmethode lautet wie folgt:

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

Hoffe das hilft jemandem. Die Quelle stammt aus einem Beitrag in meinem Blog hier: http://dev.flauschig.ch/wordpress/?p=387

Roemer
quelle
Dies ist die genaueste Antwort. Trotzdem habe ich Ihre Methode für die letzte Zeile verbessert, in der nicht immer alle Zeilen deklariert sind: pastebin.com/CVkavHgy
David Diez
Wenn Sie Console.Write verwenden, um "Ausgabe" zu drucken, können Sie diesen isFirstTeil entfernen . Mach das einfach sb.AppendLine();am Ende des Foreach.
Tomwaitforitmy
2

Sie können Tabulatoren anstelle von Leerzeichen zwischen Spalten verwenden und / oder die maximale Größe für eine Spalte in Formatzeichenfolgen festlegen ...

LaGrandMere
quelle
2

Es gibt mehrere NuGet-Pakete, die bei der Formatierung helfen können. In einigen Fällen string.Formatreichen die Funktionen von aus, aber Sie möchten möglicherweise die Größe von Spalten zumindest basierend auf dem Inhalt automatisch anpassen.

ConsoleTableExt

ConsoleTableExt ist eine einfache Bibliothek, mit der Tabellen formatiert werden können, einschließlich Tabellen ohne Gitterlinien. (Ein beliebteres Paket ConsoleTables scheint keine randlosen Tabellen zu unterstützen.) Hier ein Beispiel für die Formatierung einer Liste von Objekten mit Spalten, deren Größe auf deren Inhalt basiert:

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

Wenn Sie mehr Funktionen benötigen, können Sie mit CsConsoleFormat eine beliebige Konsolenformatierung erreichen . † Im Folgenden wird beispielsweise eine Liste von Objekten als Raster mit einer festen Spaltenbreite von 10 formatiert, wie in den anderen Antworten mit 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)
                    })
                )
        ));

Es mag komplizierter als rein aussehen string.Format, aber jetzt kann es angepasst werden. Zum Beispiel:

  • Wenn Sie die Größe von Spalten basierend auf dem Inhalt automatisch ändern möchten, ersetzen Sie sie AddColumns(10, 10, 10, 10, 10)durch AddColumns(-1, -1, -1, -1, -1)( -1ist eine Verknüpfung zu GridLength.Auto, Sie haben mehr Größenoptionen, einschließlich des Prozentsatzes der Breite des Konsolenfensters).

  • Wenn Sie die Zahlenspalten rechts ausrichten möchten, fügen Sie { Align = Right }sie dem Initialisierer einer Zelle hinzu.

  • Wenn Sie eine Spalte einfärben möchten, fügen Sie { Color = Yellow }sie dem Initialisierer einer Zelle hinzu.

  • Sie können Rahmenstile und mehr ändern.

† CsConsoleFormat wurde von mir entwickelt.

Athari
quelle
1

Ich mag die hier erwähnten Bibliotheken wirklich, aber ich hatte eine Idee, die einfacher sein könnte als nur aufzufüllen oder Tonnen von String-Manipulationen durchzuführen.

Sie können den Cursor einfach manuell mithilfe der maximalen Zeichenfolgenlänge Ihrer Daten setzen. Hier ist ein Code, um auf die Idee zu kommen (nicht getestet):

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

Sie können leicht extrapolieren, wenn Sie mehr Zeilen haben.

Sauleil
quelle
0

Machen Sie etwas Polsterung, dh

          public static void prn(string fname, string fvalue)
            {
                string outstring = fname.PadRight(20)  +"\t\t  " + fvalue;
                Console.WriteLine(outstring);

            }

Das hat zumindest bei mir gut funktioniert.

מלך המשיח
quelle