这是我对此代码的第二个问题。 此代码来自“Sams教你自己C编程”第7版第66页的修改过的脚本。 将脚本复制出书后,我对其进行了修改(只是一点点),使其更有趣。
以下是一些示例输出:
[bad_cat@KittyLitter LearningCode]$ gcc SamsC.04.seconds.c
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ):
2147483646
2147483646 seconds is equal to 68 y 35 d, 3 h, 14 m, and 6 s
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ):
2147483647
2147483647 seconds is equal to [bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ):
2147483650
-2147483646 seconds is equal to error: -2147483646 is an excessive amount of seconds.
range for seconds must be between 0 and 2147483647!
If number of seconds exceeds 2147483647, then it is beyond range for type 'int'.
EXITING seconds program.
[bad_cat@KittyLitter LearningCode]$ ./a.out
Enter the number of seconds ( > 0, < 2147483647 ):
9876543210
1286608618 seconds is equal to 40 y 291 d, 7 h, 16 m, and 58 s
[bad_cat@KittyLitter LearningCode]$
以下是代码:
/* Illustrates the modulus operator. */
/* inputs a number of seconds, and converts to hours, minutes, and seconds. */
// minute = 60 seconds : 60
// hour = 60 * 60 seconds : 3600
// day = 24 * 60 * 60 seconds : 86400
// year = 365 * 24 * 60 * 60 seconds : 31536000
#include <stdio.h> // from original script
/* Define constants */
#define SECS_PER_MIN 60 // from original script
#define MIN_PER_HOUR 60
#define HOURS_PER_DAY 24
#define DAYS_PER_YEAR 365
#define SECS_PER_YEAR 31536000
#define SECS_PER_HOUR 3600 // from original script
#define SECS_PER_DAY 86400
#define LIMIT 2147483647
unsigned seconds, minutes, hours, days, years, secs_remain, mins_remain, hours_remain, days_remain; // modified from original script
int main(void) // from original script
{
seconds = minutes = hours = days = years = secs_remain = mins_remain = hours_remain = days_remain = 0;
/* Input the number of seconds. */
printf( "Enter the number of seconds ( > 0, < %d ): \n", LIMIT ); // modified from original script
scanf( "%d", &seconds ); // from original script
years = seconds /SECS_PER_YEAR;
days = seconds / SECS_PER_DAY;
hours = seconds / SECS_PER_HOUR; // from original script
minutes = seconds / SECS_PER_MIN; // from original script
days_remain = days % DAYS_PER_YEAR;
hours_remain = hours % HOURS_PER_DAY;
mins_remain = minutes % MIN_PER_HOUR; // modified from original script
secs_remain = seconds % SECS_PER_MIN; // from original script
printf( "%d seconds is equal to ", seconds ); // from original script
if ( seconds < SECS_PER_HOUR )
{
printf( "%d m, and %d s\n", minutes, secs_remain );
return 0;
}
else if((seconds >= SECS_PER_HOUR ) && (seconds < SECS_PER_DAY ))
{
printf( "%d h, %d m, and %d s\n", hours, mins_remain, secs_remain ); // from original script
return 0; // from original script
}
else if((seconds >= SECS_PER_DAY ) && (seconds < SECS_PER_YEAR ))
{
printf( "%d d, %d h, %d m, and %d s\n", days, hours_remain, mins_remain, secs_remain );
return 0;
}
else if((seconds >= SECS_PER_YEAR ) && (seconds < LIMIT ))
{
printf( "%d y %d d, %d h, %d m, and %d s\n", years, days_remain, hours_remain, mins_remain, secs_remain );
return 0;
}
else if(seconds > LIMIT )
{
printf("error: %d is an excessive amount of seconds.\n", seconds);
printf("range for seconds must be between 0 and %d!\n", LIMIT );
printf("If number of seconds exceeds %d, then it is beyond range for type 'int'.\n", LIMIT );
printf("EXITING seconds program. \n");
return 1;
}
}
谢谢,我已将所有"%d"
更改为"%u"
和限制。
我也将它们放在一起以供将来参考:
#include <stdio.h>
#include <limits.h>
int main(void)
{
printf("\n");
printf("The number of bits in a byte =\t\t\t\t %d\n", CHAR_BIT);
printf("The maximum number of bytes in a multi-byte character =\t %d\n", MB_LEN_MAX);
printf("The minimum value of SIGNED CHAR =\t\t\t %d\n", SCHAR_MIN);
printf("The maximum value of SIGNED CHAR =\t\t\t %d\n", SCHAR_MAX);
printf("The maximum value of UNSIGNED CHAR =\t\t\t %d\n", UCHAR_MAX);
printf("The minimum value of SHORT INT =\t\t\t %d\n", SHRT_MIN);
printf("The maximum value of SHORT INT =\t\t\t %d\n", SHRT_MAX);
printf("The maximum value for an UNSIGNED SHORT INT =\t\t %u\n", USHRT_MAX);
printf("The minimum value of INT =\t\t\t\t %d\n", INT_MIN);
printf("The maximum value of INT =\t\t\t\t %d\n", INT_MAX);
printf("The maximum value for an UNSIGNED INT =\t\t\t %u\n", UINT_MAX);
printf("The minimum value of CHAR =\t\t\t\t %d\n", CHAR_MIN);
printf("The maximum value of CHAR =\t\t\t\t %d\n", CHAR_MAX);
printf("The minimum value of LONG =\t\t\t\t %ld\n", LONG_MIN);
printf("The maximum value of LONG =\t\t\t\t %ld\n", LONG_MAX);
printf("The maximum value for an UNSIGNED LONG INT =\t\t %Lu\n", ULONG_MAX);
printf("\n");
return(0);
}
答案 0 :(得分:3)
您似乎正在努力确保用户输入的seconds
变量的值不会过大。因此,您将值读入seconds
,然后(除其他外),您尝试检查它是否太大。但问题是,当你在seconds
中读取太大的值时,你无法真正说出它是什么,因为seconds
的值太大了坚持,所以它已被转化为其他价值!
现在,它有点复杂,因为您已将seconds
声明为unsigned int
。您系统上seconds
的实际范围可能是0到4294967295.因此,当您输入类似2147483648的值时,seconds
可以保留此值值 - 尽管它大于LIMIT
,所以你确实通过了else
子句。
但是,当您进入else
子句时,使用seconds
打印出%d
的值。但是%d
用于签名的整数,而不是未签名的。这就是为什么你会看到那些奇怪的负面价值。
我不确定这是否能回答您的问题,而且我不确定您真正想要您的代码做什么(也就是说,您是否真的宁愿使用有符号或无符号算术),所以我没有提供任何&#34;固定&#34;代码供您试用。但我希望这有助于解释发生了什么。如果您有更多问题,请询问。
附录:这里实际发生的是当它们溢出时,无符号整数和#34;环绕&#34;从太高的值回到0.此外,尽管它没有得到保证,但有符号的整数也往往会从它们自己太高的价值回归到大的,负的,太低的价值。
对于32位整数,值循环在4294967296的循环中。所以unsigned可以从0到4294967295,如果你试图在4294967296中堵塞,你得到0,如果你尝试4294967297,你得到1,如果你尝试4294967298,你得到2,等等。
当他们签约时,合法值从-2147483648变为+2147483647,如果你试图堵塞+2147483648,你得到-2147483648,如果你试图堵塞+2147483649,你得到-2147483647等
因此,由于2147483650大于2147483647,因此它不合适,您获得的值是2147483650 - 4294967296 = -2147483646。怎么样9876543210?方式太大了,9876543210 - 4294967296 = 5581575914这仍然太大,但5581575914 - 4294967296 = 1286608618哪个合适。这就是为什么你在上一个例子中得到了那个奇怪的数字1286608618的原因。