Як я можу вирівняти текст у стовпцях за допомогою Console.WriteLine?


78

У мене є своєрідне відображення стовпців, але кінці двох стовпців, здається, неправильно вирівняні. Це код, який я маю на даний момент:

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

Я програміст-новачок, тому, можливо, я не розумію всіх даних порад, але якщо у вас є якась порада, це буде дуже вдячна!


1
Дивіться тут більш узагальнену версію цього питання. Відповіді там також варто перевірити.
Адам Глаузер

Відповіді:


13

Замість того, щоб намагатися вручну вирівняти текст у стовпці з довільними рядками пробілів, вам слід вбудувати фактичні вкладки ( \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);
}

37
Вкладки будуть працювати добре, лише якщо ваші дані однакової довжини. Якщо у вас є дані різної довжини, вам слід використовувати відповідь royas із рядками формату.
Тім

3
Так, його набагато краща відповідь. Я підтримав його, як тільки побачив, але залишив свій на той випадок, якщо простіший підхід буде ефективнішим. Я не впевнений, чому мою прийняли, хоча ... :-)
Коді Грей

1
І не забувайте про string.PadRight () та string.PadLeft ()
nhershy

Відповідь royas не корисна, якщо ви намагаєтесь вирівняти текст із змінною шириною шрифту. Я думаю, вам потрібно використовувати комбінацію заповнення табуляцією, як у цій відповіді .
Шон

317

Спробуйте це

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


18
насправді вам не потрібно передавати метод string.format. Іншими словами, це буде те саме, що робимо: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);
Тоно Нам

63

Просто щоб додати відповідь Рої. У 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 */);

5
msdn.microsoft.com/en-us/library/txafckwd(v=vs.110).aspx має документацію щодо "вирівнювання". Дуже корисний!
Frison Alexander

4
Для того, щоб вирівнювання по лівому краю вона потім просто використовувати негативне число , як це: $"{thirtyPercentValue,-10}".
stomtech

7

Я знаю, дуже старий потік, але запропоноване рішення не було повністю автоматичним, коли довше є рядки.

Тому я створив невеликий допоміжний метод, який робить його повністю автоматичним. Просто передайте список масиву рядків, де кожен масив представляє рядок і кожен елемент масиву, а також елемент рядка.

Метод можна використовувати так:

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


Це найточніша відповідь. Тим не менше, я вдосконалив ваш метод для того останнього рядка, який не завжди містить усі оголошені рядки: pastebin.com/CVkavHgy
David Diez

Якщо ви використовуєте Console.Write для друку "вихідних даних", ви можете позбутися цієї isFirstчастини. Просто виконайте sb.AppendLine();в кінці foreach.
tomwaitforitmy

2

Ви можете використовувати вкладки замість пробілів між стовпцями та / або встановити максимальний розмір стовпця у рядках формату ...


2

Існує кілька пакетів 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)( -1це ярлик GridLength.Auto, у вас є більше параметрів розміру, включаючи відсоток ширини вікна консолі).

  • Якщо ви хочете вирівняти числові стовпці праворуч, додайте { Align = Right }до ініціалізатора комірки.

  • Якщо ви хочете забарвити стовпець, додайте { Color = Yellow }до ініціалізатора комірки.

  • Ви можете змінити стилі меж та багато іншого.

† CsConsoleFormat був розроблений мною.


1

Мені дуже подобаються згадані тут бібліотеки, але у мене була ідея, яка може бути простішою, ніж просто заповнення або виконання тонн маніпуляцій рядками,

Ви можете просто встановити курсор вручну, використовуючи максимальну довжину рядка ваших даних. Ось декілька кодів, щоб отримати ідею (не перевірено):

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

ви можете легко екстраполювати, якщо у вас більше рядків.


0

Зробіть деяку підбивку, тобто

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

            }

Це добре працювало, принаймні для мене.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.