我想使用 printf 创建这样的输出:
Name Available Required
------------- ----------------- ---------------
Something 10.1 GiB 2.3 GiB
但是使用内置的间距机制不允许在变量之后、空格之前添加测量文本(即 Gb)。问题是该文本需要包含在间距中。我努力了
"%-12.1f GiB"
在间距之后放置“GiB”。
该printf功能不会一次性完成此操作。使用中间字符串。
double gigabytes_avail;
char buf[64];
snprintf(buf, sizeof(buf), "%.1f GB", gigabytes_avail);
printf("%-12s", buf);
如果您使用的是 Visual Studio 及其编译器,您可以考虑使用sprintf_s()而不是snprintf(). 它们不是同一个功能,但sprintf_s()适合这里。
或者,您可以自己进行填充,因为printf返回写入的字符数……</p>
int column_width = 15;
double gigabytes_avail;
// Does not handle errors, printf may return -1.
int r = printf("%.1f GB", gigabytes_avail);
for (; r < column_width; r++) {
putchar(' ');
}
需要注意的是,千兆字节的符号是 GB,而不是 Gb。千兆就是千兆。
printf返回打印的字符数。
使用 1 中的值printf填充后续printf.
#include <stdio.h>
int main ( void) {
printf ( "Name Available Required\n");
printf ( "------------- ----------------- ---------------\n");
for ( int out = 0; out < 20; out += 3) {
printf ( "%-15s", "Something");
int span = printf ( "%5.1f Gb", out * 10.1);
printf ( "%*.1f Gb\n", 22 - span, out * 2.3);
}
return 0;
}
输出:
Name Available Required
------------- ----------------- ---------------
Something 0.0 Gb 0.0 Gb
Something 30.3 Gb 6.9 Gb
Something 60.6 Gb 13.8 Gb
Something 90.9 Gb 20.7 Gb
Something 121.2 Gb 27.6 Gb
Something 151.5 Gb 34.5 Gb
Something 181.8 Gb 41.4 Gb
一些编辑将产生完全左对齐的结果。
#include <stdio.h>
int main ( void) {
printf ( "Name Available Required\n");
printf ( "------------- ----------------- ---------------\n");
for ( int out = 0; out < 20; out += 3) {
printf ( "%-14s", "Something");
int span = printf ( "%.1f Gb", out * 10.1);
printf ( "%*c%.1f Gb\n", 18 - span, ' ', out * 2.3);
}
return 0;
}
完全左对齐的结果:
Name Available Required
------------- ----------------- ---------------
Something 0.0 Gb 0.0 Gb
Something 30.3 Gb 6.9 Gb
Something 60.6 Gb 13.8 Gb
Something 90.9 Gb 20.7 Gb
Something 121.2 Gb 27.6 Gb
Something 151.5 Gb 34.5 Gb
Something 181.8 Gb 41.4 Gb
有时,即使在printf()一行中创建一个可重用的宏/函数来处理各种值也很有趣。
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <math.h>
// https://stackoverflow.com/a/4589384/2410359
#define IMAX_BITS(m) ((m)/((m)%255+1) / 255%255*8 + 7-86/((m)%255+12))
// Decimal digits possible in an integer `m`
#define IMAX_DIGITS(m) (IMAX_BITS(m)*28/93 + 1) //ceiling( bits * log10(2))
#define ULLONG_STRING_SIZE (IMAX_DIGITS(ULLONG_MAX) + 1)
#define KSCALE 1000u /* or 1024u */
char* PrintMetric(char *dest, size_t n, unsigned long long b, char *suffix) {
char prefix[] = "\0kMGTPEZY";
int i = 0;
while (i < sizeof prefix - 1 && b / pow(KSCALE, i) >= 99.95) {
i++;
}
assert(i < sizeof prefix - 1);
snprintf(dest, n, "%-.1f %.1s%s", b / pow(KSCALE, i), prefix + i, suffix);
return dest;
}
#define PRT_BYTES(ull) \
(PrintMetric((char [ULLONG_STRING_SIZE]){0}, ULLONG_STRING_SIZE, (ull), "b"))
// ^----------------------------^ Compound literal
用法
注意一个printf().
#define GSCALE (1ull * KSCALE * KSCALE * KSCALE)
void fooo() {
puts("Name Available Required");
puts("------------- ----------------- ---------------");
// Notice 2 calls to PRT_BYTES()
printf("%-*s %-*s %-s\n", 13, "Something", 17, PRT_BYTES(10.1*GSCALE), PRT_BYTES(2.3*GSCALE));
printf("%-*s %-*s %-s\n", 13, "Something", 17, PRT_BYTES(99949), PRT_BYTES(99950));
printf("%-*s %-*s %-s\n", 13, "Something", 17, PRT_BYTES(0), PRT_BYTES(ULLONG_MAX));
}
int main() {
fooo();
return 0;
}
输出
Name Available Required
------------- ----------------- ---------------
Something 10.1 Gb 2.3 Gb
Something 99.9 kb 0.1 Mb
Something 0.0 b 18.4 Eb
另一种方法是使用"Gb(yte)"不在同一格式字符串中的指标并在标题中实现它们:
#include <stdio.h>
int main (void)
{
printf("Name Available (Gbyte) Required (Gbyte)\n");
printf("--------- ---------- ---------\n");
printf("Something %-12.1f %.1f ", 125.0, 1444.6);
}
输出:
Name Available (Gbyte) Required (Gbyte)
--------- ---------- ---------
Something 125.0 1444.6