随机以及时间相关函数——C语言描述
随机相关的函数
头文件 stdlib.h
相关函数 :rand 、srand
rand( rand C++ Reference )
函数声明:int rand( void );
rand函数返回一个位于 0 - RAND_MAX之间的伪随机整数。其中RAND_MAX在头文件 stdlib.h 中定义( 一般为int类型可表示的最大正整数 )。
rand函数通过一个特定的随机数生成算法生成伪随机数序列,该算法依据一个初始的种子值进行伪随机数生成。伪随机数生成可以看做一个特殊的处理过程,对于同一个输入(种子),输出的伪随机值序列总是相同的( 相对于一次程序运行 )。可使用函数 srand 设置伪随机数算法的种子,rand函数默认的种子值为1。
srand( srand C++ Reference )
函数声明: void srand( unsigned int seed);
初始化伪随机序列生成器的种子值。srand函数将伪随机数生成算法的种子使用参数 seed 初始化,使得伪随机数生成依赖于不同的种子,避免重复。通过将种子值 seed 设置为不同的可区分的值(如程序运行时的时间),可以保证生成的伪随机序列较为随机。
seed = 1时,即为伪随机序列生成算法的默认初始初始值。
示例:
#include<stdio.h>
#include<stdlib.h> #define num_of_loop 8 /*循环次数*/
void generate_random_num(void); /*产生随机序列并输出*/ int main(void)
{
generate_random_num(); /*使用默认的随机种子,即 1*/ srand( ); /*使用 5 初始化随机种子*/
generate_random_num(); srand( ); /*使用 1 初始化随机种子*/
generate_random_num(); return ;
} void generate_random_num(void)
{
int i;
for( i = ; i < num_of_loop ; i++)
printf("%d\t",rand()); printf("\n");
}
rand示例
结果如下图:

可以看到默认种子的随机序列和种子值为1的随机序列是一样的,而种子值为5的随机序列则不相同。事实上,对于同一个种子值,每次程序运行产生的随机序列都是一样的( 注意不是每次 rand 函数调用,而是每次程序运行 )。即下一次运行上述示例时,仍产生一样的伪随机序列。
为了使得由固定种子值产生的固定伪随机序列是较为随机的,可以在每次运行程序或调用 rand 函数之前使用不同的种子值来进行初始化。常用的方法是使用在函数调用之时的时间来作为种子值。
时间相关的函数
头文件:time.h
相关函数:time、clock
time( time C++ Reference )
函数声明:time_t time( time_t *timer );
time函数的参数可以为空,即 0 / NULL ,此时 time 函数返回一个 time_t 类型的日历时间;
time函数接受一个指向 time_t 类型变量的指针作为参数,函数返回一个 time_t 类型的日历时间,并将参数指针指向的变量值设置为该日历时间。
time函数返回的日历时间精确到秒级。
根据上文对随机函数的描述,我们可以使用下面的语句来对随机数序列的种子初始化,这样每次进行初始化时的种子在秒级别的精度上是不一样,故而可以做到较好的随机。
srand( (int) time(NULL) ) //使用 time 函数返回的日历时间初始化函数,在秒级进度上保证每次种子值一致
clock( clock C++ Reference )
函数声明:clock_t clock( void );
clock函数返回程序运行至clock函数处所消耗的处理器时间( 时间片数 ),若调用失败则返回 -1。
clock函数返回值为运行消耗的时间片数,一个时间片为系统设置的一个常量时间单元,不同的系统时间片长度可能不同。可以通过在程序运行的不同位置设置两个clock函数,并根据其差值获得程序运行所消耗的时间片数。在头文件 time.h 中,存在宏定义 CLOCKS_PER_SEC,定义每秒所包含的时间片数。使用时可以通过 clock 函数得到消耗的时间片数,再通过除法获得具体消耗的秒数。
其他函数:
gmtime
函数声明:struct tm* gmtime( const time_t timer );
将time_t 类型的值转换为UTC时间,并存放在一个 tm 类型的结构体中。
localtime
函数声明:struct tm* localtime( const time_t timer );
将time_t类型的值转换为本地时间,并存放在一个 tm 类型的结构体中。
actime
函数声明:char * actime( const tm *timer);
将 tm 结构体的数据转换为一个格式固定的字符串。
结构体 tm ( 摘自头文件time.h )
struct tm
{
int tm_sec; /* Seconds: 0-59 (K&R says 0-61?) */
int tm_min; /* Minutes: 0-59 */
int tm_hour; /* Hours since midnight: 0-23 */
int tm_mday; /* Day of the month: 1-31 */
int tm_mon; /* Months *since* january: 0-11 */
int tm_year; /* Years since 1900 */
int tm_wday; /* Days since Sunday (0-6) */
int tm_yday; /* Days since Jan. 1: 0-365 */
int tm_isdst; /* +1 Daylight Savings Time, 0 No DST,
/* -1 don't know */
};
可以看到,tm结构体记录了年 月 日 时 分 秒 等信息,可通过 asctime 函数转换为方便显示的字符串形式。
示例:
#include<time.h>
#include<stdio.h> int main(void)
{
char *local_time = NULL ;
char *UTC_time = NULL ;
struct tm *t_in_tm = NULL ; time_t t = time( NULL );
t_in_tm = localtime( &t ); //将time_t类型的数值参数转换为tm结构体中保存(本地时间)
local_time = asctime( t_in_tm ); //将tm类型结构体中的数值转换为字符串形式
printf("local time is %s\n",local_time); t_in_tm = gmtime( &t ); //将time_t类型的数值参数转换为tm结构体中保存(UTC时间)
UTC_time = asctime( t_in_tm ); //将tm类型结构体中的数值转换为字符串形式 printf("UTC time is %s\n",UTC_time); return ;
}
可以看到本地时间与UTC时间相差八个小时

注意:可以从示例代码中看到,在程序运行过程中,并没有声明一个具体的 tm 类型的结构体和存放字符串的数组用于存放数据,而只是声明了用于指向这些结构的指针用于存放返回值。这是由于上述函数的操作是针对一个公用的静态缓冲区来进行的,返回的参数为指向该缓冲区内具体结构的指针,故而不需要使用者另行声明。
在头文件time.h中有如下警告:

也就是说上述静态缓冲区是由函数共享的,可能被其他函数覆盖数据,使用需要小心。
实际上,笔者在书写示例代码时,首先书写的是如下程序(只保留核心部分,读者可以比较一下与上面示例的微小不同),结果输出的两个时间总是相同的,而不是相隔8个小时。
time_t t = time( NULL );
t_in_tm = localtime( &t ); //将time_t类型的数值参数转换为tm结构体中保存(本地时间)
local_time = asctime( t_in_tm ); //将tm类型结构体中的数值转换为字符串形式 t_in_tm = gmtime( &t ); //将time_t类型的数值参数转换为tm结构体中保存(UTC时间)
UTC_time = asctime( t_in_tm ); //将tm类型结构体中的数值转换为字符串形式 printf("local time is %s\nUTC time is %s\n",local_time,UTC_time);
原因解释:在第一次函数调用返回( 2,3行),函数返回的是指向静态缓冲区中 tm 结构和字符串所在内存的地址。在第二次返回对应结构的内存地址指针时( 5,6行),由于公用静态缓冲区,后续 gmtime 和 asctime 函数使用的内存空间与 localtime 和 asctime使用的内存空间相同。即第二次操作是在同样的缓冲区中操作。结果就是,local_time和UTC_time指向的是同一片内存区域,且该区域最后一次是由第6行操作改变的,从而使的两个字符串输出的都是UTC时间形式。这也从侧面反应出共用静态缓冲区可能带来的弊端。
更高精度的时间获取,可以参考博客 Windows获取当前系统时间。
随机以及时间相关函数——C语言描述的更多相关文章
- 数据结构(java语言描述)
概念性描述与<数据结构实例教程>大同小异,具体参考:http://www.cnblogs.com/bookwed/p/6763300.html. 概述 基本概念及术语 数据 信息的载体,是 ...
- Jquery如何序列化form表单数据为JSON对象 C# ADO.NET中设置Like模糊查询的参数 从客户端出现小于等于公式符号引发检测到有潜在危险的Request.Form 值 jquery调用iframe里面的方法 Js根据Ip地址自动判断是哪个城市 【我们一起写框架】MVVM的WPF框架(三)—数据控件 设计模式之简单工厂模式(C#语言描述)
jquery提供的serialize方法能够实现. $("#searchForm").serialize();但是,观察输出的信息,发现serialize()方法做的是将表单中的数 ...
- 最小正子序列(序列之和最小,同时满足和值要最小)(数据结构与算法分析——C语言描述第二章习题2.12第二问)
#include "stdio.h" #include "stdlib.h" #define random(x) (rand()%x) void creat_a ...
- c++学习书籍推荐《面向对象程序设计:C++语言描述(原书第2版)》下载
百度云及其他网盘下载地址:点我 <面向对象程序设计:C++语言描述(原书第2版)>内容丰富,结构合理,写作风格严谨,深刻地论述了c++语言的面向对象编程的各种技术,主要内容包括:面向对象编 ...
- C语言学习书籍推荐《数据结构与算法分析:C语言描述(原书第2版)》下载
维斯 (作者), 冯舜玺 (译者) <数据结构与算法分析:C语言描述(原书第2版)>内容简介:书中详细介绍了当前流行的论题和新的变化,讨论了算法设计技巧,并在研究算法的性能.效率以及对运行 ...
- 数据结构与抽象 Java语言描述 第4版 pdf (内含标签)
数据结构与抽象 Java语言描述 第4版 目录 前言引言组织数据序言设计类P.1封装P.2说明方法P.2.1注释P.2.2前置条件和后置条件P.2.3断言P.3Java接口P.3.1写一个接口P.3. ...
- 数据结构(Java语言描述)-第一章:概述
第一章 概述 1.0 序言 自己为啥要学数据结构嘞,我觉得主要有以下三个原因: 前段时间在看并发编程时,发现aqs,corrunthashmap等底层都用到了数据结构,主要的有队列,还有链表,学习数据 ...
- 《算法详解:C++11语言描述》已出版
经过漫长的编写.修订和印刷过程,书籍<算法详解:C++11语言描述>终于出版了!目前本书已在各大电商平台上架,搜索书名即可找到对应商品.本书的特色在于: 介绍最新的C++11.C++14和 ...
- 我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗
文章背景,回答提问:我想立刻辞职,然后闭关学习编程语言,我给自己3个月时间学习C语言!这样行的通吗? 我的建议是这样:1. 不要辞职.首先说,你对整个开发没有一个简单的了解,或一个系统的入门学习.换句 ...
随机推荐
- Array【数组】和Object【对象】的特性比较
数组是JavaScript提供的一个内部对象,它是一个标准的集合,我们可以添加(push).删除(shift)里面元素,我们还可以通过for循环遍历里面的元素. 那么除了数组我们在JavaScript ...
- 1.7 js基础,字符串、数组小结
一.arguments 实参参数的数组 实参[实际的值],形参[形式上的参数] 当参数个数不固定的时候使用. 示例: script> var g ...
- python中文分词工具——结巴分词
传送门: http://www.iteye.com/news/26184-jieba
- 解决WORD2013输入时光标老跳的问题
Word2013有一个非常影响使用的bug.就是在编辑文档时,光标会乱跑,影响输入.微软给出了一个kb2863845 160多MB的补丁包,安装完成后就可以解决这个问题. 补丁下载链接: 链接:ht ...
- FileReader实现上传图片前本地预览
平时做图片上传预览时如果没有特殊的要求就直接先把图片传到后台去,成功之后拿到URL再渲染到页面上.或者使用前端插件.这篇博客使用的是HTML5的新特性——FileReader.由于兼容性,这种方法不适 ...
- log4j 详细讲解
日志是应用软件中不可缺少的部分,Apache的开源项目log4j是一个功能强大的日志组件,提供方便的日志记录.在apache网站:jakarta.apache.org/log4j 可以免费下载到Log ...
- Nexus-NuGet私有仓库服务搭建(一)
搭建私有Nuget服务器的方式有很多,大多数人文章介绍在vs 中新建默认web项目,然后再Nuget 中安装 Nuget.Server,再部署到IIS 中即可.虽然能用,但是这种方式太过简陋,操作界面 ...
- docker 安装ElasticSearch的中文分词器IK
首先确保ElasticSearch镜像已经启动 安装插件 方式一:在线安装 进入容器 docker exec -it elasticsearch /bin/bash 在线下载并安装 ./bin/ela ...
- poj 1141 Brackets Sequence ( 区间dp+输出方案 )
http://blog.csdn.net/cc_again/article/details/10169643 http://blog.csdn.net/lijiecsu/article/details ...
- wget http://pypi.python.org/packages/source/s/setuptools/setuptools-2.0.tar.gz 下载时报错 ssl is required 解决办法
方法一:使用浏览器下载.在浏览器中输入 http://pypi.python.org/packages/source/s/setuptools/setuptools-2.0.tar.gz 方法二:将h ...