分类: C/C++
2008-05-31 09:30:17
/ * Convert a date into an unsigned long integer. Return zero if
* the date is invalid. This uses bit fields and a union.
*/
unsigned long DateToNumber(int month, int day, int year)
{
YearConverter yc;
/ * Make all of the ranges begin at zero * /
--month;
--day;
year - = 1975;
/ * Make sure all of the date elements are in proper range * /
if (
( year<0 || year>127) || /* Keep the year in range */
( month<0 || month>11)|| / * Keep the month in range * /
( day <0 || day>31) /* Keep the day in range */
)
return 0;
yc. date. day = day;
yc. date. month = month;
yc. date. year = year;
return yc. number+1;
}
/ * Take a number and return the values for day, month, and year
* stored therein. Very elegant due to use of bit fields.
*/
void NumberToDate(unsigned long number, int * month,
int * day , int * year )
{
YearConverter yc;
yc. number = number-1;
* month = yc. date. month+ 1;
* day = yc. date. day+ 1;
* year = yc. date. year+ 1975;
}
/*
* This tests the routine and makes sure it is OK.
*/
main()
{
unsigned long n;
int m, d, y;
n = DateToNumber( 11,22,1980);
if (n == 0)
{
printf( \"The date was invalid. \\n\" ) ;
exit(1);
}
NumberToDate( n, &m, &d, &y);
printf ( \"The date after transformation is : %d/%d/%d. \\n\" ,
m, d, y) ;
}
由于有些月份不足31天,因此上述程序的某些部分效率仍然不高。此外,每月天数的不同将给日期的增值运算和差值运算带来困难。好在C语言中有些现成的函数能非常出色地完成这些更为复杂的任务,它们可以使程序员少写很多代码。请参见:
13.2怎样把时间存储到单个数字中?有这方面的标准吗?
13.2 怎样把时间存储到单个数字中?有这方面的标准吗?
把时间存储到单个数字中与把日期存储到单个数字中是类似的,因此,你可以先阅读一下13.1。另一方面,这两者之间也有差别。
首先,你应该注意到,一天中的时间比一年中的日期有更强的“确定性”。你知道一分钟内有多少秒,一小时内有多少分,一天内有多少小时。这种确定性使时间处理起来更容易,而且不容易出错。
在选择把时间转换为数字的方法时,你最好遵循下面这些原则:
·应该尽可能地节约存储空间;
·应该能存储不同种类的时间(标准的,军用的);
·应该使时间使用起来又快又高效。
如果你已经阅读了13.1,你可能会认为处理这个问题的一个好办法就是用位域来表示时间。这确实是一个不错的办法,有其巧妙之处。请看下面这个把时间表示为一个整数的程序:
/*
* The bit field structures for representing time
*/
typedef struct
{
unsigned int Hour : 5;
unsigned int Minute :6;
} TimeType;
typedef union
{
TimeType time;
int Number;
} TimeConverter;
/*
* Convert time to a number, returning zero when the values are
* out of range.
*/
int TimeToNumber( int Hour, int Minute)
{
TimeConverter convert;
if (Hour
return 0;
convert, time. Hour = Hour;
convert, time. Minute = Minute;
return convert. Number+ 1;
}
/*
* Convert a number back into the two time
* elements that compose it.
*/
void NumberToTime( int Number, int *Hour, int * Minute)
{
TimeConverter convert;
convert. Number = Number - 1;
* Hour = convert. time. Hour;
* Minute = convert. time. Minute;
}
/*
* A main routine that tests everything to
* ensure its proper functioning.
*/
main()
{
int Number, Hour, Minute;
Hour=13;
Minute = 13;
Number = TimeToNumber( Hour, Minute);
NumberToTime( Number, &Hour, &Minute) ;
printf( \"The time after conversion is %d:%d. \\n\" , Hour, Minute);
}
在时间表示中加入秒是很容易的,你只需在TimeType结构中加入一个秒域,并在每个转换函数中多加一个参数。
但是,假设你想把转换所得的数字用作时钟,让它整天“滴答滴答”地走个不停,你应该怎样做呢?如果用位域来完成这项任务,你就先需要把数字转换为位域,然后增加秒值,并检测秒值是否达到了60;如果秒值达到了60,你还需要增加分值,并再次检测分值是否达到了60……。这个过程太繁琐了!
这里的问题是:TimeType结构中的各个成员并不是刚好能纳入一个位域——它们的上限临界值并不是2的幂。因此,用数学的方法表示时间更好。这做起来相当简单,你可以用从当天开始时到当天某一点为止所度过的秒(或分)数来表示该点的时间。如果你用这种方法表示时间,那么在相应的数字上加1就相当于在时间上加1秒(或分)。下面的程序就是用这种方法表示时间的:
# include
# include
/*
* A subroutine to convert hours and minutes into an
* integer number. This does not checking for the sake
* of brevity (you\'ve seen it done before!).
*/
int TimeToNumber(int Hours, int Minutes)
{
return Minutes+ Hours * 60;
}
/*
* Convert an integer to hours and minutes.
*/
void NumberToTimeC int Number, int * Hours, int * Minutes)
{
* Minutes = Number % 60;
* Hours = Number / 60;
}
/*
* A quickie way to show time.
*/
void ShowTime(int Number)
{
int Hours, Minutes;
NumberToTimeC Number, &Hours, &Minutes);
printf(\"%02d:%02d\\n\", Hours, Minutes);
}
/*
* A main loop to test the salient features of the time class.
*/
main()
{
int Number, a;
Number = TimeToNumber(9,32);
printf(\"Time starts at :%d\" , Number);
ShowTime(Number);
/*
* Assure yourself that minutes are added correctly.
* /
for( a = 0; a<10; + +a)
{
printf( \"After 32 minutes :\");
Number + = 32; / * Add 32 minutes to the time. * /
ShowTime(Number);
}
}
这个程序提供了一种更好的表示时间的方法。它容易操作,并且更为紧凑。它的代码还可以进一步压缩,加入秒的表示留给读者作为练习。
这种格式类似于C函数timelocal()和timegm()所使用的格式,这些函数都可以从任意给定的时间/日期开始计算秒数。只要对本章所提供的时间和日期处理程序稍作修改,你就可以使用这些程序了,而且还可以使用你自己定义的时间格式。
请参见:
13.1怎样把日期存储到单个数字中?有这方面的标准吗?
13.5存储时间的最好方法是哪一种?
13.3 为什么定义了这么多不同的时间标准?
由于所使用的计算机和编译程序不同,你可能会发现定义了许多时间标准。尽管有多种时间标准会带来一定的方便,但把它们都写出来显然要花很长的时间,并且把它们都存储起来也会多占硬盘空间。那么,为什么还要这样呢?其中有好几个原因。
首先,C是一种可移植的语言。因此在一台计算机上编写的C程序应该能在另一台计算机上运行。通常,当用C语言在一个新的系统上进行开发时,必须把专门在某个系统上使用的那些函数添加到C语言中。此后,当C程序需要从一个系统移植到另一个系统中时,将具体命令添加到目标系统中通常就很容易了。这样一来,同一函数的不同版本就都汇集在C语言中了。这种情况就曾多次发生在时间函数身上。
其次,时间(和日期)可能有多种不同的用法。你可能想按秒计时,可能想从一个具体的时间和日期开始计时。此外,你还可能想按最小的时间间隔计时,以确保计时尽可能精确。对于计时,没有一种最好的方法。当你开始编写一个涉及到时间的程序时,你必须先把可以使用的函数分析一遍,并确定哪一种函数最适合于你的目的。如果你要用多种方法处理时间,你就可能要使用多种不同的时间格式和函数。在这种情况下,你可能会庆幸有这么多时间格式可供选择,并且其中的一种能满足你的需要。
请参见: .
13.1怎样把日期存储到单个数字中?有这方面的标准吗?
13.2怎样把时间存储到单个数字中?有这方面的标准吗?
13.4存储日期的最好方法是哪一种?
13.5存储时间的最好方法是哪一种?
13.4 存储日期的最好方法是哪一种?
简而言之,并不存在一种存储日期的最好方法。对存储日期的方法的选择依赖于你究竟要做什么,你可能想把日期存成一个整数(可能是从历史上的某一天开始计算的天数),或者存成一个含月、日、年和其它信息的结构,或者存成一个文本字符串。文本字符串看起来并不实用,并且难以处理,但你应该看到它自有用处。
如果你只是记录一个数字型日期,这个问题就简单多了。你应该使用一种固有的格式,或者用一个整数来表示时间,等等。你还应该确定是否要存储当前日期,是否要更新日期,是否要检查两个日期之间的间隔,等等。完成这些任务的方法有许多种,并且它们大多使用c标准库中所含的格式和函数。但是,如果你在程序的设计中过早地定下一种格式,你就会受到限制。为了保持开阔的思路和程序的灵活性,你应该根据具体情况使用最合适的函数。
但是,你可能想用更复杂的方式表示日期。通常你会用多种不同的方法记忆日期。你不可能总是记住每一件事的准确日期,相反,你可能会把生活中一个重要的日期记成“我16岁生日聚会后的第三天”,或者把一个历史日期记成“奥特曼帝国覆灭后的第十年”。这样的日期不能用简单的数字或结构来表示,它们需要使用更复杂的方式。在存储这种相对日期的同时,你还可能想存储对一个计算机能够处理的已知日期的引用,或者存储一个固定日期。这种办法对日期的排序和操作是有帮助的。
请参见:
13.1 怎样把日期存储到单个数字中?有这方面的标准吗?
13.5 存储时间的最好方法是哪一种?
存储时间的最好方法完全依赖于存储时间的目的和将要施加到时间值上的操作。下面将举出一些时间的不同用途,分析一下它们将有助于你更好地选择时间的存储方法。
假设你只需要记录事件发生的时间,并且要以“实时”方式记录。换句话说,你想确定某一事件发生的真实时间。你要记录的事件可能包括一个文件的创建。一个长而复杂的程序的开始和结束,或者写完一本书的某一章的时间。在这种情况下,你需要从计算机的系统时钟中取出当前时间并存储起来。较好并且较简单的方法是用一个现成的时间函数取出时间,并且直接按原来的格式存储起来。这种方法基本上不需要你做什么工作。
由于种种原因,你可能不想用标准C函数提供的格式存储时间。你可能想用一种更简单的格式,以使操作更加容易,或者想用不同的方式表示时间。在这种情况下,用一个整数值表示时间是个好办法,这种方法在13.2中曾介绍过。这种方法使时间使用起来又快又简单,而且使你可以比较不同的时间,看看哪一个更早。
与处理日期一样,计算时间也可以使用相对的方法,但这些方法很难量化。虽然“午后半小时”并不难量化,但“我吃完午饭后”就很难量化了。尽管这并不是记录时间的最简单的方法,但在有些情况下,这却是唯一的方法。在这些情况下,除了存储描述时间的文本字符串,你别无选择,而此时这也是最好的存储方法。