理解 %*d 和 if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 )) 在 c
To understand %*d and if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 )) in c
我必须在 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
,如果成功,将 return 值 1
(实际上,它将 return 成功读取的东西的数量,但是,因为你只要求一件事,那是你能得到的最多的东西)。如果失败,你会得到别的东西。
因此与 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
作为格式说明符会更容易。
如果您对更简洁和结构化的解决方案感兴趣,您可能会发现这很有帮助。如果它是教育性工作,请不要使用它,因为它的目的是让你自己学会做,但看到另一种方法会很有帮助。
此代码分解出执行单行的逻辑,打印足够的元素以从最大值下降到 1 然后再次备份(但设置最小值以基于行打印)。
然后主代码只打印出足够多的行,以便每行的中间值从最大值下降到 1,然后再次备份(基本上每行使用相同的逻辑)。
#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函数)
Returns
3 The scanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the
event of an early matching failure.
在这个 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 );
}
我必须在 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
,如果成功,将 return 值 1
(实际上,它将 return 成功读取的东西的数量,但是,因为你只要求一件事,那是你能得到的最多的东西)。如果失败,你会得到别的东西。
因此与 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
作为格式说明符会更容易。
如果您对更简洁和结构化的解决方案感兴趣,您可能会发现这很有帮助。如果它是教育性工作,请不要使用它,因为它的目的是让你自己学会做,但看到另一种方法会很有帮助。
此代码分解出执行单行的逻辑,打印足够的元素以从最大值下降到 1 然后再次备份(但设置最小值以基于行打印)。
然后主代码只打印出足够多的行,以便每行的中间值从最大值下降到 1,然后再次备份(基本上每行使用相同的逻辑)。
#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函数)
Returns
3 The scanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
在这个 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 );
}