C 中的输出缩进



基本上我想打印这样的东西:

Process No.(Size)    Block No.(Size)
1(200)               3(300)
2(3)                 1(50)
3(1000)              4(1200)

由于间距是可变的,那么如何通过%d中的宽度说明符来做到这一点?

printf("%d(%d)%d(%d)",processNo,processSize,blockNo,blockSize)

间距值放在哪里?

您可以先将表的每个"字段"打印为字符串,然后使用左对齐的固定宽度格式说明符打印每个此类字段字符串。后者是使用-标志和%s格式说明符(即-n%s)中的width值完成的。

以下代码显示您需要的内容(我使用这些字段来保存列标题和每行数据,但这是一个"可选的附加内容")。

#include <stdio.h>
int main(void)
{
// Test data ...
int procNo[3] = { 1, 2, 3 };
int procSize[3] = { 200, 3, 1000};
int blockNo[3] = { 3, 1, 4 };
int blockSize[3] = { 300, 50, 1200 };
char procField[32] = "Process No.(Size)";
char blockField[32] = "Block No.(Size)";
// Print rubric ...
printf("%-22s%-22sn", procField, blockField);
// Print data rows ...
for (int i = 0; i < 3; ++i) {
// Write each field to string ...
snprintf(procField, sizeof(procField), "%d(%d)", procNo[i], procSize[i]);
snprintf(blockField, sizeof(blockField), "%d(%d)", blockNo[i], blockSize[i]);
// ... then print fields as left-justified, fixed-length fields
printf("%-22s%-22sn", procField, blockField);
}
return 0;
}

printf有两个很少使用的功能,可以简单直接地完成此操作。

第一个特征是来自printf的返回值。是的,printf实际上返回了一些东西,它是打印的字符数。请考虑以下两行代码:

int width = printf("Process No.(Size)    ");
int used  = printf("%d(%d)", procNum[i], procSize[i]);

第一行打印列标题,并将变量width设置为该标题中的字符数。第二行打印流程信息,并将变量used设置为打印两个数字和括号所需的字符数。因此,进程信息结束和块信息开头之间所需的空格字符数简直是width - used

第二个功能是可变字段宽度说明符。来自手册页:">字段宽度和/或精度可以用星号'*'[...]在这种情况下,int参数提供字段宽度或精度。">请考虑以下代码行:

printf("%*s", width - used, "");

代码使用"%s"转换说明符打印字符串,但字符串""为空,因此通常不会打印任何内容。但我们使用了星号作为字段宽度。所以字符串(width - used)前面的参数提供字段宽度。字符串将填充空格以填充该宽度。

请注意,如果width - used小于 1,则代码应将字段宽度设置为 1,以便在进程信息和块信息之间至少插入一个空格。

将它们放在一起,代码如下所示:

#include <stdio.h>
#define max(a,b) ((a) > (b) ? (a) : (b))
int main(void)
{
int procNum[]   = { 1, 2, 3 };
int procSize[]  = { 200, 3, 1000 };
int blockNum[]  = { 3, 1, 4 };
int blockSize[] = { 300, 50, 1200};
int width = printf("Process No.(Size)    ");    // print first column header, and save the width
printf("Block No.(Size)n");
for (int i = 0; i < 3; i++)
{
int used = printf("%d(%d)", procNum[i], procSize[i]);      // print process information, and save the number of characters used
printf("%*s%d(%d)n", max(width - used, 1), "", blockNum[i], blockSize[i]);   // print spaces followed by the block information
}
}

有关如何将宽度作为参数传递给printf的示例,请参阅 printf 格式字符串中的"宽度字段"小节。

我从 C 中查找整数的长度中获得了宽度算法。

我在Code Chef测试了我的代码。如果您打算使用gcc编译此代码,您将需要-lm选项来引入库以进行math.h。请参阅如何编译使用 math.h 的 C 程序?。

如果您需要不同的表头,则可以在printspaces(11-w)中调整常量11和printspaces(5-w)中的常量5,直到数据与标题对齐。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int width(int v){
return floor(log10(abs(v))) + 1;
}
int printspaces(int s){
int x;
for (x=0;x<s;x++)
printf(" ");
}
int main(void){
int i,j,w;
int a[3][4] = {{1,200,3,300},{2,3,1,50},{3,1000,4,1200}};
//int a[3][4] = {{10,200,37,3000},{278,3565,1131,50},{390,100,4567,1200}};
char *separator[4]  = {"","","","n"};
printf("Process No.(Size)   Block No.(Size)n");
for(i=0;i<3;i++){
for (j=0;j<4;j++){
w = width(a[i][j]);
if (j%2==0){
printspaces(11-w);
printf("%*d%s",w,a[i][j],separator[j]);
}
else{
printf("(%*d)",w,a[i][j]);
printspaces(5-w);
printf("%s",separator[j]);
}
}
}
return 0;
}

以下是结果(对于代码中的两个示例数组):

int a[3][4] = {{1,200,3,300},{2,3,1,50},{3,1000,4,1200}};
Process No.(Size)   Block No.(Size)
1(200)            3(300)  
2(3)              1(50)   
3(1000)           4(1200) 

int a[3][4] = {{10,200,37,3000},{278,3565,1131,50},{390,100,4567,1200}};
Process No.(Size)   Block No.(Size)
10(200)           37(3000) 
278(3565)        1131(50)   
390(100)         4567(1200) 

最新更新