用printf()的格式说明符“%*.*s”绘制菱形

Draw rhombus with the format specifier "%*.*s" of printf()

我正在尝试对一个小程序进行编码,以便使用标准 printf 在屏幕上打印一个菱形,直到现在我有这段代码,正如您在编译时看到的那样,它没有打印出所需的输出:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int i, n = 5;
    for(i = -n/2; i < n; i++)
    printf("%*.*s\n", n / 2 + 1, i, "*****");
    return 0;
}

谁能告诉我应该怎么做?

期望的输出:

一种方式:

#include <stdio.h>
#include <stdlib.h>
int main() { 
 for(int i=1;i<10;i++)
   printf("%.*s%.*s\n",abs(5-i),"            ",9-abs(10-(i<<1)),"**********");
 return 0;
}

另一个选项:

#include <stdio.h> 
#include <stdlib.h>
int main(void)
{
    for (int n = 11, i = -n / 2; i < n / 2 + 1; i++)
        printf("%*.*s\n", n - abs(i), 1 + (n / 2 - abs(i)) * 2, "***********");
    return 0;
}

其他答案演示了如何用时髦的数学来解决问题。另一种方法是使用软件状态机解决问题。状态机有3个状态变量

  • skip -- 行首空格数
  • show -- 行中显示的星号(星星)数
  • delta -- 用于调整每次循环时的跳过和显示

这种状态变量的安排使 printf 更容易理解。 skip+show 是一行中的字符总数,show 是要从 stars 字符串中取出的星号数,而 stars 字符串必须长于show.

的最大值
char *stars = "*********************";
printf( "%*.*s\n", skip + show, show, stars );

所以问题是如何在每次循环时更新状态变量,以及循环终止条件是什么。

n=5 为例,skip 的值序列是

4 3 2 1 0 1 2 3 4

我们通过初始设置 skip = n-1delta = -1 来完成此操作。将 delta 添加到 skip 会导致 skip 递减直到达到 0。我们不允许 skip 变为负数,而是强制 skip = 1delta = 1 改变方向。然后 skip 递增,直到达到 n,从而终止循环。

show 的值序列是

1 3 5 7 9 7 5 3 1

这个序列是从show=1开始,通过-2*delta调整生成的。

char *stars = "*********************";

int n = 5;
int skip = n - 1;
int delta = -1;
int show = 1;
while ( skip < n )
{
    printf( "%*.*s\n", skip + show, show, stars  );

    skip += delta;
    if ( skip < 0 )
    {
        skip = 1;
        delta = 1;
    }

    show -= delta * 2;
}