web-dev-qa-db-fra.com

Comment aligner du texte dans les colonnes avec Console.WriteLine?

J'ai une sorte d'affichage de colonne, mais les deux dernières colonnes semblent ne pas s'aligner correctement. C'est le code que j'ai pour le moment:

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

Je suis un programmeur débutant, donc je ne comprends peut-être pas tous les conseils donnés, mais si vous avez des conseils, ce serait grandement apprécié!

73
Stephen Smith

Au lieu d'essayer d'aligner manuellement le texte dans des colonnes avec des chaînes d'espaces arbitraires, vous devez incorporer des tabulations réelles (la séquence d'échappement \t) dans chaque chaîne de sortie:

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);
}
13
Cody Gray

Essaye ça

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

où le premier nombre à l'intérieur des accolades est l'index et le second l'alignement. Le signe du deuxième nombre indique si la chaîne doit être alignée à gauche ou à droite. Utilisez des nombres négatifs pour aligner à gauche.

Ou regardez http://msdn.Microsoft.com/en-us/library/aa331875(v=vs.71).aspx

270
royas

Juste pour ajouter à la réponse de roya. En c # 6.0, vous pouvez maintenant utiliser une interpolation de chaîne:

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

Cela peut en fait être une ligne sans tous les dollars supplémentaires, je pense juste que cela le rend un peu plus facile à lire comme ça.

Et vous pouvez également utiliser une importation statique sur System.Console, vous permettant de faire ceci:

using static System.Console;

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

Je sais, très vieux fil, mais la solution proposée n'était pas complètement automatique quand il y a de plus longues chaînes.

J'ai donc créé une petite méthode d'assistance qui le fait de manière entièrement automatique. Il suffit de passer une liste de tableaux de chaînes où chaque tableau représente une ligne et chaque élément du tableau, ainsi qu'un élément de la ligne.

La méthode peut être utilisée comme ceci:

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

La méthode d'assistance est la suivante:

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

J'espère que ça aide quelqu'un. La source provient d'un article de mon blog ici: http://dev.flauschig.ch/wordpress/?p=387

6
Roemer

Plusieurs paquets NuGet peuvent vous aider à formater. Dans certains cas, les capacités de string.Format sont suffisantes, mais vous pouvez au moins redimensionner automatiquement les colonnes en fonction du contenu.

ConsoleTableExt

ConsoleTableExt est une bibliothèque simple qui permet de formater des tableaux, y compris des tableaux sans lignes de grille. (Un paquet plus populaire ConsoleTables ne semble pas prendre en charge les tableaux sans bordure.) Voici un exemple de formatage d'une liste d'objets avec des colonnes dimensionnées en fonction de leur contenu:

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

Si vous avez besoin de plus de fonctionnalités, la mise en forme de la console peut être réalisée avec CsConsoleFormat . † Par exemple, voici la mise en forme d’une liste d’objets sous forme de grille avec une largeur de colonne fixe de 10, comme dans les autres réponses utilisant 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)
                    })
                )
        ));

Cela peut sembler plus compliqué que string.Format pur, mais il peut maintenant être personnalisé. Par exemple:

  • Si vous souhaitez redimensionner automatiquement les colonnes en fonction du contenu, remplacez AddColumns(10, 10, 10, 10, 10) par AddColumns(-1, -1, -1, -1, -1) (-1 est un raccourci vers GridLength.Auto, vous avez davantage d'options de dimensionnement, notamment le pourcentage de largeur de la fenêtre de la console).

  • Si vous souhaitez aligner les colonnes numériques à droite, ajoutez { Align = Right } à l'initialiseur d'une cellule.

  • Si vous souhaitez colorer une colonne, ajoutez { Color = Yellow } à l'initialiseur d'une cellule.

  • Vous pouvez modifier les styles de bordure et plus encore.

† CsConsoleFormat a été développé par moi.

2
Athari

Vous pouvez utiliser des tabulations au lieu d'espaces entre les colonnes et/ou définir la taille maximale d'une colonne dans les chaînes de format ...

2
LaGrandMere

J'aime vraiment les bibliothèques mentionnées ici, mais j'avais une idée qui pourrait être plus simple que de simplement rembourrer ou de manipuler des tonnes de cordes,

Vous pouvez simplement définir manuellement votre curseur en utilisant la longueur de chaîne maximale de vos données. Voici du code pour avoir l'idée (non testé):

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

vous pouvez facilement extrapoler si vous avez plus de lignes.

0
Sauleil