我必须在c中打印此图案
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
而且我发现与此相关的代码
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main()
{
while ( 1 )
{
printf( "Enter a non-negative number (0 - exit): " );
int n;
if ( ( scanf( "%d", &n ) != 1 ) || ( n <= 0 ) ) break;
if ( INT_MAX / 2 < n )
{
n = INT_MAX / 2;
}
int width = 1;
for ( int tmp = n; tmp /= 10; ) ++width;
putchar( '\n' );
int m = 2 * n - 1;
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < m; j++ )
{
int value1 = abs( n - i - 1 ) + 1;
int value2 = abs( n - j - 1 ) + 1;
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
}
putchar( '\n' );
}
putchar( '\n' );
}
return 0;
}
我想知道为什么在此语句中使用scanf( "%d", &n ) != 1
if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 ));
以及这里的单一格式说明符如何接受两个值
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
为什么%和*一起使用"%*d"
??
[scanf("%d", &n)
表达式将尝试读入n
的整数,如果成功,将返回值1
(实际上,它将返回成功读取的事物的数量,但是,因为您只是在问一方面,这是您将获得的最多回报)。如果失败,您还会得到其他东西。
因此,与1
的比较是为了确保其有效。如果您没有获得1
,则出了点问题。
语句printf( "%*d ", width, something)
实际上与printf("%5d", something)
紧密相关(它将打印一个至少五个字符宽的字段),但是使用变量5
而不是固定的width
。
因此下面的两个printf
调用是等效的:
int val = 42;
int wid = 5;
printf("%5d", val);
printf("%*d", wid, val);
由于在您提供的代码中width
总是看起来像是1
,所以我不确定为什么这样完成。在我看来,仅使用%d
作为格式说明符会更容易。
如果您对更简洁,结构化的解决方案感兴趣,您可能会发现这很有帮助。如果这是教育工作,请不要使用它,因为这样做的目的是要自己学习,但是查看另一种方法会有所帮助。
[此代码排除了执行单行的逻辑,打印足够多的元素以从最大值减小到一个,然后再次备份(但设置一个最小值以根据该行打印)。
然后,主代码仅打印出足够多的行,以使每行的中间值从最大值减小到一,然后又再次返回(基本上与每行使用相同的逻辑)。
#include <stdio.h>
// Code to print out a single line, values going from max down to min then back up.
static void outLine(int max, int min) {
for (int i = max; i > 0; i--) printf("%d ", i < min ? min : i);
for (int i = 2; i <= max; i++) printf("%d ", i < min ? min : i);
putchar('\n');
}
int main() {
while ( 1 ) {
// Get the value, <1 means stop.
int n;
printf( "\nEnter a non-negative number (< 1 = exit): " );
if ((scanf("%d", &n) != 1) || (n <= 0)) break;
// Do each line, max down to 1 then back up.
for (int i = n; i > 0; i--) outLine(n, i);
for (int i = 2; i <= n; i++) outLine(n, i);
}
return 0;
}
成绩单是,按要求:
pax> ./testProg
Enter a non-negative number (< 1 = exit): 2
2 2 2
2 1 2
2 2 2
Enter a non-negative number (< 1 = exit): 3
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
Enter a non-negative number (< 1 = exit): 4
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
Enter a non-negative number (< 1 = exit): -42
来自C标准(7.21.6.4 scanf函数)
返回
3 scanf函数如果输入则返回宏EOF的值在第一次转换(如果有)完成之前发生故障。否则,scanf函数将返回分配的输入项目数,该数量可以小于或小于指定的输入项目数,甚至为零。早期匹配失败的事件。
在此if语句中
if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 ));
子表达式( scanf( "%d", &n ) != 1 )
,是否成功调用了scanf
,也就是变量n
是否从用户那里获得了值。如果是这样(在成功的情况下),则第二个子表达式( n <= 0 )
检查输入的值是否为非正值。
即,如果scanf调用未成功或用户设置了非正值,则由于break语句,控件将传递到while循环之外。结果,程序完成了执行。
在printf的此调用中
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
格式转换说明符%*d
指定将输出字段(*
)的宽度设置为调用(width
)的自变量,表达式value1 < value2 ? value2 : value1
在这两个值之间选择最大值value1
和value2
。
您可以通过以下方式重写该调用pf printf
if ( value1 < value2 )
{
printf( "%*d ", width, value2 );
}
else
{
printf( "%*d ", width, value1 );
}