文档章节

C和指针---第十六章:标准函数库

fzyz_sb
 fzyz_sb
发布于 2013/09/23 19:28
字数 2855
阅读 66
收藏 0

16.1 整型函数

16.1.1 算术<stdlib.h>

int abs( int value );
long int labs( long int value );
div_t div( int numerator, int denominator );
ldiv_t ldiv( long int number, long int denom );
abs函数返回它的参数的绝对值.如果其结果不能用一个整数表示,这个行为是未定义的.labs用于执行相同的任务,但它的作用对象是长整数.

div函数把它的第二个参数(分母)除第一个参数(分子),产生商和余数,用一个div_t结构返回.这个结构包含以下两个字段:

int quote;
int rem;
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	div_t	dt;
	printf("%d\n", abs( -123 ) );
	dt = div( 123, 12 );
	printf("%d---%d\n", dt.quot, dt.rem );

	return 0;
}
程序输出:

16.1.2 随机数<stdlib.h>

int rand( void );
void srand( unsigned int seed );
通常通过rand+srand来产生随机数:通过srand初始化随机数发生器,通过rand来获得随机数.
#include <stdlib.h>
#include <time.h>
#define TRUE	1
#define FALSE	0

void shuffle( int *deck, int n_cards )
{
	int		i;
	static	int	first_time = TRUE;

	/*
	*如果尚未初始化,用当天的当前时间作为随机数发生器
	*/
	if ( first_time ){
		first_time = FALSE;
		srand( ( unsigned int )time( NULL ) );
	}

	/*
	*通过交换随机对的牌进行"洗牌"
	*/
	for ( i = n_cards - 1; i > 0; i-- ){
		int		where;
		int		temp;

		where = rand() % i;

		temp = deck[ where ];
		deck[ where ] = deck[ i ];
		deck[ i ] = temp;
	}
}
16.1.3 字符串转换<stdlib.h>
int atoi( char const *string );
long int atol( char const *string );
long int strtol( char const *string, char **unused, int base );
unsigned long int strtoul( char const *string, char **unused, int base );
strtol保存一个指向转换值后面第一个字符的指针.如果函数的第二个参数并非为NULL,这个指针便保存在第二个参数所指向的位置.这个指针允许字符串的剩余部分进行处理而无需推测转换在字符串的哪个位置终止.


16.2 浮点型函数

头文件math.h包含了函数库中剩余的数学函数的声明.这些函数的返回值以及绝大多数参数都是double类型.

16.2.1 三角函数<math.h>

double sin( double angle );
double cos( double angle );
double tan( double angle );
double asin( double value );
double acos( double value );
double atan( double value );
double atans( double x, double y );
备注:angle是弧度.

16.2.2 双曲函数<math.h>

double sinh( double angle );
double cosh( double angle );
double tanh( double angle );

16.2.3 对数和指数函数<math.h>

double exp( double value );
double log( double value );
double log10( double value );
16.2.5 幂<math.h>
double pow( double x, double y );
double sqrt( double x );
16.2.6 底数,顶数,绝对值和余数
double floor( double x );
double ceil( double x );
double fabs( double x );
double fmod( double x, double y );
floor返回不大于其参数的最大整数值.ceil返回不小于其参数的最大整数值.

fabs返回其参数的绝对值,fmod返回参数x除y得到的余数.

16.2.7 字符串转换<stdlib.h>

double atof( char const *string );
double strtod( char const *string, char **unused );

16.3 日期和时间函数

16.3.1 处理器时间<time.h>

clock函数返回从程序开始执行处理器所消耗的时间:

clock_t clock( void );
如果要显示秒,则初一CLOCKS_PER_SEC即可.
#include <stdio.h>
#include <time.h>

int main(void)
{
	clock_t t1 = clock();
	clock_t t2;
	int		i = 0;
	
	for ( i = 0; i < 100000000; i++ )
		;
	t2 = clock();

	printf("%d---%d---%d\n", t1, t2, t2 - t1 );
	printf("%d\n", CLOCKS_PER_SEC );

	return 0;
}
程序输出:

16.3.2 当天时间<time.h>

time函数返回当前的日期和时间

time_t time( time_t *return_value );
如果参数是一个非空的指针,时间值也将通过这个指针进行存储.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void)
{
	time_t *tt = malloc( sizeof( time_t ) );
	time( tt );

	printf("%d\n", tt );
	free( tt );

	return 0;
}
但是,返回值貌似不太对哦,不同的运行,显示不同的答案.

于是,我对代码进行了修改(书上明显介绍有误,不知道是不是翻译的问题):

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void)
{
	time_t tt;
	tt = time( NULL );

	printf("%d\n", tt );

	return 0;
}
现在,程序正常输出了:

转换到年:

日期和时间的转换

char *ctime( time_t const *time_value );
double difftime( time_t time1, time_t time2 );
接下来的两个函数把一个time_t值转换为一个tm结构,后者允许我们很方便地访问日期和时间的各个组成部分:
struct tm *gmtime( time_t const *time_value );
struct tm *localtime( time_t const *time_value );
备注:tm结构中月份是从0开始的,而年是从1900开始的.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int main(void)
{
	time_t tt1;
	time_t tt2;
	time_t *ptt = &tt1;
	struct tm *tm1;
	int		i = 0;
	int		j = 0;
	tt1 = time( NULL );

	for ( i = 0; i < 100000000; i++ )
		for ( j = 0; j < 10; j++ )
			;

	tt2 = time( NULL );

	printf("%s\n", ctime( ptt ) );
	printf("%d----%d\n", tt1, tt2 );
	printf("the time waste %d\n", difftime( tt2, tt1 ) );
	tm1 = gmtime( ptt );
	printf("%d---%d", tm1->tm_mon + 1, tm1->tm_year + 1900 );


	return 0;
}
程序输出:

我不理解的是:为什么tt2的时间居然是0???

唉,把%d改为%d吧.


而mktime函数把一个tm结构转换为一个time_t值.

time_t mktime( struct tm *tm_ptr );
16.4 非本地跳转

     setjmp和longjmp函数提供了一种类似goto语句的机制,但它并不局限于一个函数的作用域之内.这些函数常用于深层嵌套的函数调用链.如果在某个低层的函数中检测到一个错误,你可以立即返回到顶层函数,不必向调用链中的每个中间层返回一个错误标志.

#include <setjmp.h>
int setjmp( jmp_buf state );
void longjmp( jump_buf state, int value );
你声明一个jmp_buf变量,并调用setjmp函数对它进行初始化,setjmp的返回值为0.setjmp把程序的状态信息保存到跳转缓冲区.你调用setjmp时所处的函数便成为你的"顶层"函数.

以后,在顶层函数或其他任何它所调用的函数内的任何地方调用longjmp函数,将导致这个被保存的状态重新恢复.longjmp的效果就是使执行流通过再次从setjmp函数返回,从而立即跳回到顶层函数中.

备注:具体参考<UNIX高级环境编程>一书.


16.7 执行环境

16.7.1 终止执行<stdlib.h>

void abort( void );
void atexit( void (func)( void ) );
void exit( int status );
abort函数用于不正常地终止一个正在执行的程序.由于这个函数将引发SIGABRT信号,你可以在程序中为这个信号设置一个信号处理函数,在程序终止之前采取任何你想采取的动作,甚至可以不终止程序.

atexit函数可以把一些函数注册为推出函数.当程序将要正常终止时,退出函数将被调用.退出函数不能接受任何参数.

当exit函数被调用时,所有被atexit函数注册为退出函数的函数将按照它们所注册的顺序被反序依次调用.然后,所有用于流的缓冲区被刷新,所有打开的文件被关闭.用tmpfile函数创建的文件被删除.然后,退出状态返回给宿主环境,程序停止执行.

16.7.2 断言<assert.h>

断言就是声明某种东西应该为真.

void assert( int expression );
当它被执行时,这个宏对表达式参数进行测试.如果它的值为假,它就向标准错误打印一条诊断信息并终止程序.

增加:

#define NDEBUG
后,消除所有的断言.

16.7.5 排序和查找<stdlib.h>

void qsort( void *base, size_t n_elements, size_t el_size, int ( *compare )( void const *, void const * ) );
#include <stdlib.h>
#include <string.h>

typedef struct {
	char key[10];
	int other_data;
} Record;

int r_compare( void const *a, void const *b )
{
	return strcmp( ( ( Record* )a)->key, ( ( Record* )b)->key );
}

int main(void)
{
	Record array[50];

	qsort( array, 50, sizeof( Record ), r_compare );

	return EXIT_SUCCESS;
}
bsearch用于二叉树查找:
void *bsearch( void const *key, void const *base, size_t n_elements, size_t el_size, int ( *compare )( void const *, void const * ) );
#include <stdlib.h>
#include <string.h>

typedef struct {
	char key[10];
	int other_data;
} Record;

int r_compare( void const *a, void const *b )
{
	return strcmp( ( ( Record* )a )->key, ( ( Record* )b )->key );
}

int main(void)
{
	Record array[50];
	Record key;
	Record *ans;

	strcpy( key.key, "value" );
	ans = bsearch( &key, array, 50, sizeof( Record ), r_compare );

	return EXIT_SUCCESS;
}

习题:

1. 

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int func( int value )
{
	return ceil( ( value - 9) / 2 );
}

int main( int ac, char **av )
{
	printf("%d\n", func( 41 ) );
	printf("%d\n", func( 45 ) );
	printf("%d\n", func( 34 ) );

	return 0;
}

程序输出:

2.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main( int ac, char **av )
{
	int i = 0;
	srand( ( unsigned int )time( NULL ) );

	for ( i = 1; i <= 18; i++ ){
		printf("%d ", rand() % 6 );
		if ( !( i % 6 ) ){
			printf("\n");
		}
	}

	return 0;
}

程序输出:

4.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


int main( int ac, char **av )
{
	struct tm tm1;
	tm1.tm_year = 2013 - 1900;
	tm1.tm_mon = 9 - 1;
	tm1.tm_mday = 24;
	tm1.tm_hour = 0;
	tm1.tm_isdst = 0;
	tm1.tm_min = 0;
	tm1.tm_sec = 0;
	tm1.tm_yday = 0;

	mktime( &tm1 );

	printf("%d", tm1.tm_wday );


	return 0;
}

程序输出:

5.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define A 10.45
#define B 10.00
#define C -1.0
#define X 1.78816

double wind_chill( double temp, double velocity )
{
	double V = velocity;
	double t = 33 - temp;

	return 33 - ( A + B * sqrt( V ) + C * V ) * t / ( A + B * sqrt( X ) + C * X );	//书上并未说要用33减,可能是翻译的问题!!
}

int main( int ac, char **av )
{
	printf("%f\n", wind_chill( -5, 10 ) );

	return 0;
}
程序输出:

6.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

double payment( double amount, double interest, int year )
{
	double A = amount;
	double N = year * 12;
	double I = interest * 1.0 / 12 / 100;

	return A * I  / ( 1 - pow( 1 + I, -N ) );
}

int main( int ac, char **av )
{
	printf("%f\n", payment( 100000, 8, 20 ) );

	return 0;
}
程序输出:

7.

1)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void func( int arr[], int randValue )
{
	int i = 0; 
	for ( i = 0; i < 10; i++ ){
		arr[i] = 0;
	}

	for ( i = 0; i < 10000; i++ ){
		arr[ rand() % randValue ]++;
	}
}

void printArr( int arr[], int len )
{
	int i = 0;
	for ( i = 0; i < len; i++ ){
		printf("%d ", arr[i] );
	}
	printf("\n");
}
int main(void)
{
	int temp[10];
	int i = 0;

	for ( i = 0; i < 10; i++ ){
		temp[i] = 0;
	}

	srand( ( unsigned int )time( NULL ) );

	for ( i = 2; i <= 10; i++ ){
		func( temp, i );
		printArr( temp, i );
	}

	return 0;
}
程序输出:

2)

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void func( int arr[][10], int randValue )
{
	int i = 0;
	int j = 0;
	int preValue = 0;
	for ( i = 0; i < 10; i++ ){
		for ( j = 0; j < 10; j++ ){
			arr[i][j] = 0;
		}
	}

	for ( i = 0; i < 10000; i++ ){
		preValue = rand() % randValue;
		arr[ preValue ][ rand() % randValue ]++;
	}
}

void printArr( int arr[][10], int len )
{
	int i = 0;
	int j = 0;
	for ( i = 0; i < len; i++ ){
		for ( j = 0; j < len; j++ ){
			printf("%3d ", arr[i][j]);
		}
		printf("\n");
	}
	printf("\n---------------------\n");
}
int main(void)
{
	int temp[10][10];
	int i = 0;
	int j = 0;

	for ( i = 0; i < 10; i++ ){
		for ( j = 0; j < 10; j++ ){
			temp[i][j] = 0;
		}
	}

	srand( ( unsigned int )time( NULL ) );

	for ( i = 2; i <= 10; i++ ){
		func( temp, i );
		printArr( temp, i );
	}

	return 0;
}

程序输出过长,截取一半:

8.之前写过,略过.

9. 概率很怪,有时候100%,有时候0%,也有时候13.4%

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void init( int arr[] )
{
	int i = 0;
	for ( i = 0; i < 365; i++ ){
		arr[i] = 0;
	}
}

void func( int arr[] )
{
	int i = 0;
	init( arr );	
	srand( ( unsigned int )time( NULL ) );

	for ( i = 0; i < 30; i++ ){
		arr[ rand() % 365 ]++;
	}
}

int isHave( int arr[] )
{
	int i = 0;
	for ( i = 0;i < 365; i++ ){
		if ( arr[i] > 1 ){
			return 1;
		}
	}

	return 0;
}

int main(void)
{
	int i = 0;
	int j = 0;
	int arr[365];
	double count = 0;

	for ( i = 0; i < 10000; i++ ){
		func( arr );
		if ( isHave( arr ) ){
			count++;
		}
		init( arr );
	}

	printf("%.2f%%", count * 100.0 / 10000 );

	return 0;
}
程序输出:

2)概率不稳啊!!!

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void init( int arr[] )
{
	int i = 0;
	for ( i = 0; i < 365; i++ ){
		arr[i] = 0;
	}
}

void func( int arr[], int num )
{
	int i = 0;
	init( arr );	
	srand( ( unsigned int )time( NULL ) );

	for ( i = 0; i < num; i++ ){
		arr[ rand() % 365 ]++;
	}
}

int isHave( int arr[] )
{
	int i = 0;
	for ( i = 0;i < 365; i++ ){
		if ( arr[i] > 1 ){
			return 1;
		}
	}

	return 0;
}

int main(void)
{
	int i = 0;
	int j = 0;
	int arr[365];
	double count = 0;
	int		peopleNum = 0;

	for ( i = 1; i < 100; i++){
		for ( j = 0; j < 10000; j++ ){
			func( arr, i );
			if ( isHave( arr ) ){
				count++;
			}
			init( arr );
		}

		if ( count * 100.0 / 10000 >= 50){
			peopleNum = i;
			break;
		}
		count = 0;
	}

	printf("%d\n", peopleNum );

	return 0;
}
程序输出:

10.

#include <stdio.h>
#include <stdlib.h>

void moveArr( int arr[], int len, int maxLen )
{
	int i = 0; 
	for ( i = maxLen; i > len; i-- ){
		arr[i + 1] = arr[i];
	}
}

void insert_sort( int arr[], int value )
{
	static int maxLen = 0;
	int i = 0;
	maxLen++;
	if ( 1 == maxLen )
	{
		arr[0] = value;
		return;
	}
	for ( i = 0; i < maxLen - 1; i++ ){
		if ( arr[i] > value ){
			moveArr( arr, i - 1, maxLen - 1 );
			arr[i] = value;
			break;
		}
	}

	if ( i == maxLen - 1 ){
		arr[i] = value;
	}
}

int main(void)
{
	int arr[11];		//请多分配一个空间,用于移位
	int i = 0;

	for ( i = 0; i < 10; i++ ){
		arr[i] = 0;
	}

	insert_sort( arr, 1 );
	insert_sort( arr, 9 );
	insert_sort( arr, 2 );
	insert_sort( arr, 8 );
	insert_sort( arr, 7 );
	insert_sort( arr, 3 );
	insert_sort( arr, 4 );
	insert_sort( arr, 6 );
	insert_sort( arr, 5 );
	insert_sort( arr, 0 );

	for ( i = 0; i < 10; i++ ){
		printf("%d ", arr[i]);
	}

	return 0;
}

程序输出:



© 著作权归作者所有

共有 人打赏支持
fzyz_sb
粉丝 408
博文 209
码字总数 447144
作品 0
武汉
程序员
[编程语言]C陷阱与缺陷

内容摘要 作者以自己1985年在Bell实验室时发表的一篇论文为基础,结合自己的工作经验扩展成为这本对C程序员具有珍贵价值的经典著作。写作本书的出发点不是要批判C语言,而是要帮助C程序员绕过...

21gprs
2014/05/23
0
0
C++快速入门

只学过Java的我最近笔试接触到各种C++的题目,于是稍微恶补了一下C++的基础部分,以下内容是基于《21天学通C++》的部分读书笔记,按照章节写的。 第二章 C++程序的组成部分 ①#include 预处理...

waffle930
2016/10/02
56
0
c++ primer 第五版学习笔记

第二章 函数体外定义的内置类型变量会初始化为0,函数体外的是未初始化的 用constexpr声明变量表示它是一个常量表达式(编译器可以确定的值),且只能应用于字面值 c++11中可以用 来定义一个...

David栗子
2017/12/11
0
0
业余爱好者的C程序设计学习之路

我学习和工作的方向都是化工,和 IT 专业一点边都不搭,属于程序设计爱好者一类。坚持了很多年了,谈谈我的认识。 一、为什么是C 汇编太难,直接下手会吓死宝宝的。 basic 不能考虑,因为“对...

四彩
2016/02/04
107
2

没有更多内容

加载失败,请刷新页面

加载更多

71.告警系统主脚本 配置文件 监控项目

20.20 告警系统主脚本(main.sh) 20.21 告警系统配置文件 20.22 告警系统监控项目 20.20 告警系统主脚本(main.sh): ~1.约定:把以后所有的shell脚本放在/usr/local/sbin下,也方便我们查...

王鑫linux
3分钟前
0
0
装饰者模式

装饰者模式 Q:何为装饰模式? ()地给一个对象添加一些额外的(),并且()时,并不影响原对象。扩展功能来说,装饰器模式相比生成子类更为灵活。 Q:使用场景? 1.想要在不影响其他对象的情况下...

阿元
23分钟前
0
0
GO 切片(slice)相关语法

package mainimport("fmt")func main() {var intArr [5]int = [...]int{1,2,3,4,5} //定义一个数组slice := intArr[2:4] //第二个(包含)下标到第四个下标(不包含)fmt.Println...

汤汤圆圆
25分钟前
0
0
活动招募 HUAWEI HiAI公开课·北京站-如何在4小时把你的APP变身AI应用

人工智能和机器学习是全球关注的新趋势,也是当前最火爆、最流行的话题。当你拿手机用语音助手帮你点外卖,智能推荐帮你把周边美食一网打尽;当你拿起P20拍照时,它将自动识别场景进行最美优...

华为终端开放实验室
39分钟前
1
0
匹配两位小数,js正则

var regex = /^\d*(\.[1-9]|\.\d[1-9])*$/ console.log(1.2,regex.test(1.2)); console.log(0.3,regex.test(0.3)); console.log(1.03,regex.test(1.03)); ......

微信小程序-暗潮
44分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部