Как выровнять число как это в C? - PullRequest
31 голосов
/ 16 апреля 2009

Мне нужно выровнять ряд чисел в C с помощью printf () , как в этом примере:

-------1
-------5
------50
-----100
----1000

Конечно, между всеми этими числами есть цифры, но это не относится к рассматриваемой проблеме ... О, рассмотрите тире как пробелы, я использовал тире, чтобы было легче понять, что я хочу.

Я могу это сделать только:

----1---
----5---
----50--
----100-
----1000

Или это:

---1
---5
--50
-100
1000

Но ничего из этого я не хочу, и я не могу добиться того, что показано в первом примере, используя только printf (). Возможно ли это вообще?

EDIT:
Извините, я спешил и плохо объяснил себя ... Мой последний пример и все ваши предложения (использовать что-то вроде "% 8d") не работают, потому что, хотя последнее число равно 1000, это не так обязательно пройти весь путь до 1000 или даже 100 или 10 в этом отношении.

Независимо от количества отображаемых цифр, я хочу, чтобы самое большее 4 пробела было не более 4 пробелов. Допустим, мне нужно отобразить цифры от 1 до 1000 (A) и от 1 до 100 (B), и я использую для обоих «% 4d» это будет вывод:

A:

---1
....
1000

Какой вывод я хочу ...

B

---1
....
-100

Что не является выводом, который я хочу, я на самом деле хочу это:

--1
...
100

Но, как я уже сказал, я не знаю точное число цифр, которые я должен напечатать, он может иметь 1 цифру, он может иметь 2, 3 или более, функция должна быть подготовлена ​​для всех. И я хочу еще четыре дополнительных пробела, но это не так важно.

РЕДАКТИРОВАТЬ 2: Кажется, что то, что я хочу, так, как мне это нужно, невозможно (проверьте ответы Дэвида Торнли и Бланка Ксавьера и мои комментарии). Спасибо всем за ваше время.

Ответы [ 9 ]

46 голосов
/ 16 апреля 2009

Почему printf("%8d\n", intval); не работает для вас? Стоит ...

Вы не показывали строки формата ни для одного из ваших "не работающих" примеров, поэтому я не уверен, что еще вам сказать.

#include <stdio.h>

int
main(void)
{
        int i;
        for (i = 1; i <= 10000; i*=10) {
                printf("[%8d]\n", i);
        }
        return (0);
}

$ ./printftest
[       1]
[      10]
[     100]
[    1000]
[   10000]

РЕДАКТИРОВАТЬ: ответ на уточнение вопроса:

#include <math.h>
int maxval = 1000;
int width = round(1+log(maxval)/log(10));
...
printf("%*d\n", width, intval);

Расчет ширины вычисляет логарифмическую базу 10 + 1, которая дает количество цифр. Причудливый * позволяет использовать переменную для значения в строке формата.

Вам все еще нужно знать максимум для каждого конкретного прогона, но на любом языке, карандаше и бумаге это никак не обойти.

45 голосов
/ 17 апреля 2009

Поиск это в моем удобном Harbison & Steele ....

Определите максимальную ширину полей.

int max_width, value_to_print;
max_width = 8;
value_to_print = 1000;
printf("%*d\n", max_width, value_to_print);

Имейте в виду, что max_width должен иметь тип int для работы со звездочкой, и вам придется рассчитывать его на основе того, сколько места вы хотите иметь. В вашем случае вам придется рассчитать максимальную ширину наибольшего числа и добавить 4.

3 голосов
/ 16 апреля 2009
    printf("%8d\n",1);
    printf("%8d\n",10);
    printf("%8d\n",100);
    printf("%8d\n",1000);
1 голос
/ 17 апреля 2009

Попробуйте преобразовать в строку, а затем используйте «% 4.4s» в качестве спецификатора формата. Это делает формат фиксированной ширины.

0 голосов
/ 28 ноября 2013
#include<stdio.h>
int main()
{
 int i,j,n,b;
 printf("Enter no of rows ");
 scanf("%d",&n);
 b=n;
 for(i=1;i<=n;++i)
 {
    for(j=1;j<=i;j++)
    {
        printf("%*d",b,j);
        b=1;
    }
        b=n;
    b=b-i;
    printf("\n");


 }
 return 0;
}
0 голосов
/ 17 апреля 2009

Глядя на отредактированный вопрос, вам нужно найти количество цифр в наибольшем числе, которое будет представлено, а затем сгенерировать формат printf(), используя sprintf() или %*d с количеством передаваемых цифр. как int для * и затем значения. Получив наибольшее число (и вы должны определить это заранее), вы можете определить количество цифр с помощью алгоритма «целочисленного логарифма» (сколько раз вы можете разделить на 10, прежде чем доберетесь до нуля), или используя snprintf() с нулевой длиной буфера, формат %d и null для строки; возвращаемое значение говорит вам, сколько символов было бы отформатировано.

Если вы не знаете и не можете определить максимальное число перед его появлением, вы находитесь в снукере - вы ничего не можете сделать.

0 голосов
/ 17 апреля 2009

Если вы не можете знать ширину заранее, то ваш единственный возможный ответ будет зависеть от размещения вашего вывода во временном буфере некоторого вида. Для небольших отчетов проще всего собрать данные и отложить вывод до тех пор, пока ввод не будет ограничен.

Для больших отчетов может потребоваться промежуточный файл, если собранные данные превышают разумные пределы памяти.

Как только у вас есть данные, вы можете просто обработать их в отчете, используя идиому printf("%*d", width, value) для каждого значения.

В качестве альтернативы, если выходной канал разрешает произвольный доступ, вы можете просто написать черновик отчета, который предполагает (короткую) ширину по умолчанию, а затем искать и редактировать его всякий раз, когда ваше допущение ширины нарушается. Это также предполагает, что вы можете заполнить строки отчета за пределами этого поля каким-то безобидным способом или что вы готовы до сих пор заменить вывод процессом чтения-изменения-записи и отказаться от черновика файла.

Но если вы не сможете заранее предсказать правильную ширину, не будет возможности делать то, что вы хотите, без какой-либо формы двухпроходного алгоритма.

0 голосов
/ 17 апреля 2009

Насколько я могу судить по вопросу, количество требуемого отступа будет варьироваться в зависимости от имеющихся у вас данных. Соответственно, единственное решение для этого состоит в том, чтобы сканировать данные перед печатью, чтобы выяснить самое широкое значение и, таким образом, найти значение ширины, которое вы можете передать в printf с помощью оператора asterix, например,

loop over data - get correct padding, put into width

printf( "%*d\n", width, datum );
0 голосов
/ 16 апреля 2009

Итак, вы хотите 8-символьное поле с пробелами в качестве отступа? Попробуйте "% 8d". Вот ссылка .

РЕДАКТИРОВАТЬ : То, что вы пытаетесь сделать, не может быть обработано одним только printf, потому что он не будет знать, какое самое длинное число вы пишете. Вам нужно будет вычислить наибольшее число перед выполнением любых printfs, а затем выяснить, сколько цифр использовать в качестве ширины вашего поля. Затем вы можете использовать snprintf или аналогичный файл, чтобы сразу создать формат printf.

char format[20];
snprintf(format, 19, "%%%dd\\n", max_length);
while (got_output) {
    printf(format, number);
    got_output = still_got_output();
}
...