标准库函数
整形函数
分为三类
-
算数
-
随机数
-
字符串转换
算数<stdlib.h>
int abs(int value);//返回绝对值 long int labs(long int value);//返回绝对值 div_t div(int numerator, int denominator);//第二个参数除以第一个,返回商和余数 //返回值结构 int quot;//商,如果不能整除则是小于实际的结果的最大整数,为负数的时候不确定 int rem;//余数 ldiv_t div(long int number, long int deno)
随机数<stdlib.h>
int rand(void); void srand(unsignde int seed);
rand
返回一个范围在0到RAND_MAX的随机数,至少为32767
srand
设置随机数srand((unsigned int)time(0));
设置为时间
字符串转换<sdlib.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);
atoi atol
:转换的值以10为基数
strtol strtoul
:转换的时候指定基数,在转换结束的时候把下一个字符的指针存放在unused之中,基数为0的时候任何用于书写整数的数字面值都会被书写,包括"0x234"这种,在基数为11-36的时候a-z被翻译为10-35
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 int main(void) 5 { 6 char *b; 7 long int a; 8 char **c = &b; 9 a = strtol("590bear", c, 12);//e对于十二进制是非法的,返回的指针指向e 10 printf("%ld\n", a); 11 a = strtol("0x123", c, 0); 12 printf("%ld\n", a); 13 a = strtol("00101", c, 2); 14 printf("%ld\n", a); 15 return 0; 16 } resule: 9947 //11+12*12*9+12*12*12*5 291 5
当返回值出错的时候会把错误传入
erno
,传入ERANGE,并返回错误标志
函数 返回值 strtol
返回值太大为负数,LONG_MIN,太大为正数,LONG_MAX strtoul
太大返回UNLONG_MAX
浮点型函数<math.h>
函数库中的返回值、参数大部分为double
定义域错误errno
设置为EDOM
太大函数返回HUGE_VAL,太小返回0,有可能会把errno
设置为ERANGE
三角函数
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 atan2(double x, double y);
sin cos tan
的参数是一个用弧度表示得知,返回对应的值
asin acos atan
返回的是反正弦函数,反余弦,反正切asin atan
返回值是一个-π/2-π/2,cos
的是0-π
atan2
使用y/x的值求反正切的值,通过两个数的符号决定象限,返回值为-π-π
双曲函数
double sinh(double angle); double cosh(double angle); double tanh(double angle);
对数指数函数
double exp(double x); double log(double x); double log10(double x);
exp返回e的x次幂
log返回log以x的底数
log10以10为底数
浮点数表示
根据编译器格式存储一个浮点数
double frexp(double value, int *exponent); double ldexp(double fraction,int exponent); double modf(double value, double *ipart);
fraction X 2 ^ exponent = value
frexp
返回fraction
ldexp
返回value 用于在不能兼容浮点格式的机器之间传递信息
modf
把一个小数分解为两部分,整数部分存储以第二个参数,小数部分返回值
幂
double pcw(double x, double y); double sqrt(double x);
pcw
返回x的y次幂x^y,如果x是一个负数,y不是一个整数就会出现定义域错误
sqrt
函数返回参数的平方根,为负数出现定义域错误
底数、顶数、绝对值和余数
double floor(double x); double cell(double x); double fabs(double x); double fmod(double x, double y);
floor
返回不大于这个数的最大整数
cell
返回不小于的最小值
fabs
返回其参数的绝对值
fmod
返回x除以y的余数
字符转转换
double atof(char const *string); double strtod(char const *string, char **unused);
参数前有空白直接忽略,然后把合法的字符转换为一个double,忽略结尾的非法字符
strtod
会返回一个指向下一个参数的指针
没有合法的参数返回0,如果过大存储不下
errno
存储ERANGE这个值函数返回HUGE_VAL
日期和时间函数
处理时间<time.h>
clock_t clock(void);
这个值可能是一个近似值,如果要更精确的值,可以再main函数最开始调用,然后用两个数相减,如果机器不能提供时间,或者时间太大返回-1,程序开始执行到调用这个函数的时间
返回的是一个数字,是处理器滴答的次数, 转换为秒应该除以常量CLOCK_PER_SEC
当天时间
time_t time(time_t *retrun_value);
返回的时间通过这个指针传递, 时间太大的话返回-1,标准没有定义具体的格式,最好不要直接使用
时间日期的转换
char *ctime(time_t const *time_value); double difftime(time_t time_t time2);
ctime
的参数是一个指向time_t的指针,返回的是一个字符串格式
1 #include <stdio.h> 2 #include <time.h> 3 #include <stdlib.h> 4 int main(void) 5 { 6 char *a, *b; 7 a = (char *)malloc(30); 8 b=a;//地址备份用于释放内存 9 time_t time_n; 10 time(&time_n); 11 a = ctime(&time_n);//这个时a的值会发生改变 12 printf("%s", a); 13 free(b); 14 return 0; 15 16 } result: Sat Jul 30 13:23:52 2022
difftime
计算time1-time2的值,把结果转换为秒
struct tm *gmtime(time_t const *time_value); struct tm *localtime(time_t const *time_value);
用来把time_t的格式转换为一个结构体
gmtime
转为世界协调时间UTC
localtime
转换为本地时间
tm结构体
类型 | 范围 | 含义 |
---|---|---|
int tm_sec | 0-61 | 分之后的秒数 |
int tm_min | 0-59 | 小时之后的分钟数 |
int tm_hour | 0-23 | 午夜之后的小时数 |
int tm_mday | 1-31 | 当月的日期 |
int tm_mon | 0-11 | 1月后的月份,从零开始 |
int tm_year | 0-?? | 1900年之后的年数 |
int tm_wday | 0-6 | 星期日后的天数 |
int tm_yday | 0-365 | 一月一日之后的天数 |
int tm_isdat | 夏令时标志 |
1 #include <stdio.h> 2 #include <time.h> 3 int main() 4 { 5 time_t time_n; 6 struct tm *tp; 7 time(&time_n);//获取时间 8 tp = gmtime(&time_n);//时间转换为结构体 9 printf("time: %s", ctime(&time_n));//转换为字符串 10 printf("hour:%d\n", tp->tm_hour); 11 printf("min:%d\n", tp->tm_min); 12 printf("mday:%d\n", tp->tm_mday); 13 } result: time: Sat Jul 30 15:26:22 2022 hour:15 min:26 mday:30
-
结构体的操作
char *asctime(struct tm const *tm_ptr); size_t strftime(char *string, size_t maxsize, char const *format, struct tm const *tm_ptr);
asctime
把结构体转换为一个字符串,和ctime
的格式一样
strftime
把字符串转换为一个,字符串的长度小于maxsize
,被复制到第一个参数,返回值为字符串的长度,当字符串长度大于maxsize
返回-1
代码 | 由……代替 |
---|---|
%% | 一个%字符 |
%a | 星期的某一天,以当地星期几的格式简写 |
%A | 星期的某一天,以当地星期几的格式全写 |
%b | 月份,当地简写 |
%B | 全写 |
%c | 日期和时间使用%x和%X |
%d | 一个月的第几天 0-31 |
%H | 小时24小时制 0-23 |
%I | 12小时制 0-12 |
%J | 一年的第几天 001-365 |
%m | 月份 01-12 |
%M | 分钟 00-59 |
%P | AM或者PM |
%S | 秒 0-61 |
%U | 第几个星期 周日为第一天 |
%w | 星期的第几天 0-6 |
%W | 第几个星期 周一为第一天 |
%x | 日期 |
%X | 时间 |
%y | 当前世纪的年数 |
%Y | 年份全写 |
%Z | 时区简写 |
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <time.h> 4 int main(void) 5 { 6 time_t t; 7 char *c, *b; 8 struct tm *p; 9 c = (char *)malloc(40); 10 b=c; 11 time(&t); 12 p = localtime(&t); 13 14 strftime(c, 40, "a = %a\n", p); 15 printf("%s", c); 16 strftime(c, 40, "A = %A\n", p); 17 printf("%s", c); 18 strftime(c, 40, "b = %b\n", p); 19 printf("%s", c); 20 strftime(c, 40, "B = %B\n", p); 21 printf("%s", c); 22 strftime(c, 40, "c = %c\n", p); 23 printf("%s", c); 24 strftime(c, 40, "d = %d\n", p); 25 printf("%s", c); 26 strftime(c, 40, "H = %H\n", p); 27 printf("%s", c); 28 strftime(c, 40, "I = %I\n", p); 29 printf("%s", c); 30 strftime(c, 40, "J = %J\n", p); 31 printf("%s", c); 32 strftime(c, 40, "m = %m\n", p); 33 printf("%s", c); 34 strftime(c, 40, "M = %M\n", p); 35 printf("%s", c); 36 strftime(c, 40, "P = %P\n", p); 37 printf("%s", c); 38 strftime(c, 40, "S = %S\n", p); 39 printf("%s", c); 40 strftime(c, 40, "U = %U\n", p); 41 printf("%s", c); 42 strftime(c, 40, "w = %w\n", p); 43 printf("%s", c); 44 strftime(c, 40, "W = %W\n", p); 45 printf("%s", c); 46 strftime(c, 40, "x = %x\n", p); 47 printf("%s", c); 48 strftime(c, 40, "X = %X\n", p); 49 printf("%s", c); 50 strftime(c, 40, "y = %y\n", p); 51 printf("%s", c); 52 strftime(c, 40, "Y = %Y\n", p); 53 printf("%s", c); 54 strftime(c, 40, "Z = %Z\n", p); 55 printf("%s", c); 56 57 free(b); 58 59 60 } result a = Sat A = Saturday b = Jul B = July c = Sat Jul 30 15:58:04 2022 d = 30 H = 15 I = 03 J = %J //出错没有这个参数 m = 07 M = 58 P = pm S = 04 U = 30 w = 6 W = 30 x = 07/30/22 X = 15:58:04 y = 22 Y = 2022 Z = CST
time_t mktime(struct tm *tm_ptr);
把结构体转换为size_t格式
非本地跳转<setjmp.h>
类似于goto
但是范围不限于一个函数的作用域之内,常用于深层函数嵌套链
int setjmp(jmp_buf state); void longjmp(jump_buf state, int value);
声明一个
jmp_buf
的变量,使用setjmp对他初始化,返回值为0,同时把程序的状态进行保存,调用时候的函数成为顶层函数,之后使用longjmp
函数进行返回
longjmp
就是通过让执行流,通过再次从setjump返回,返回值是value,必须为一个非零的值
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <setjmp.h> 4 5 jmp_buf restart; 6 void func(void) 7 { 8 printf("func\n"); 9 longjmp(restart, 1); 10 printf("below\n"); 11 } 12 int main(void) 13 { 14 int value; 15 value = setjmp(restart); 16 if(value == 0) 17 { 18 printf("value = 0\n"); 19 func(); 20 } 21 else if(value == 1) 22 printf("value =1\n"); 23 return 0; 24 } result: value = 0 func value =1
当顶层函数返回的时候,保存的状态就不再有效了
信号
大多数的事件发生都是由程序引发的,例如执行各种语句请求输入,但是有些事件不是由程序本身引起的,常见的例子就是用户中断程序,必须对这种事件做出反应
信号是一种事件,可能是异步发生的,通常默认是终止程序,但是可以设置
信号名<signed.h>
信号 | 含 义 |
---|---|
SIGABRT | 程序请求异常终止 |
SIGFPE | 算数错误 |
SIGILL | 检测到非法的指令 |
SIGSEGV | 检查内存的非法访问 |
SIGINT | 交互性注意信号 |
SIGTREM | 终止程序的请求 |
SIGABRT:
abort
函数引起SIGFPE:上溢、下溢、除零
SIGILL:非法的CPU指令
SIGSEGV:访问不存在的地址,或者不属于程序的地址,以及地址没有对齐
SIGINT:用户中断程序,一般设置处理函数
SIGTREM:另一种用于处理中断的信号,一般不设置处理函数
处理信号<signed.h>
int raise(int sig);
可以主动引发一个信号,和自助引发的作用一样
void ( *signal(int sig, void(* hander)(int)))(int);
参数是一个信号名以及一个没有返回值, 接受一个整形函数的指针, 函数的返回参数是一个同样的指针
返回的是之前的处理函数的指针, 失败返回SIG_ERR
参数中的是要设置的指针
第二个参数SIG_DFL缺省处理,SIG_IGN忽略信号
信号处理函数
一个已经设置处理函数的信号发生的时候,首先系统恢复信号的缺省行为, 防止处理函数内部也发生这个信号导致无限循环,然后信号调用函数触发,信号代码为参数传递给函数
信号函数处理的情况是有限的,信号如果是异步的, 也就是说不是abrot
和raise
引起的不要使用signal.h
以外的库函数,而除了能给一个volatile sig_atomic_t
的静态变量赋值以外无法访问其他静态变量
程序的其他地方检查变量的值,来确定是不是有信号产生
sig_atomic_t定义了一种CPU可以以原子的方式访问的数据类型, 也就是不可分割的访问单位, 因为访问不是这种数据的时候有中间步骤, 可能会产生新的信号
标准信号处理可以使用exit() abort()
函数但是由于这两个是库函数, 所以当被异步处理的时候可能不能正常运行
volatile
数据
信号的处理可能会发生在任何时候, 要处理的变量可能会在任何时候发生改变, 这个关键字告诉编译器防止他修改程序含义的方式优化程序
示例
if(value){ printf("True"); } else{ printf("False"); } if(value){ printf("True"); } else{ printf("False"); }
可能会被优化为
if(value){ printf("True"); printf("True"); } else{ printf("False"); printf("False"); }
但是由于信号可能在任何时候产生, 所以有可能导致结果的不同
信号处理函数返回
从信号处理函数返回到信号发生的地方, 例外是SIGFPE(计算出错),由于计算不能完成, 结果未知
如果希望再次捕捉同样的信号, 要在返回之前用
signal
函数重新设置
由于不同的机器处理方式不同, 有可能不会定义所有的符号, 有的也不会回到缺省的状态, 所以移植姓会降低
打印可变参数列表<stdarg.h>
int vprintf(char const *format, va_list arg); int vfprintf(FILE *stream, char const *format, va_list arg); int vfprintf(char *buffer, char const *format, va_list arg);
va_list
必须用va_start
初始化
执行环境
终止执行<stdlib.h>
void abort(void); void atexit(void (func)(void)); void exit(int status);
abort
不正常的终止一个正在运行的程序,引发信号
atexit
用来把一些函数注册为退出函数.当函数正常终止的时候用(exit
或者main
的return
),退出函数被调用,有多个的时候按照注册的顺序依次执行
exit调用之后注册的函数依次调用, 然后用于流的缓冲区刷新,所有打开的文件关闭,
tmpfile
创建的文件删除
注:在注册的函数之中调用exit有可能会导致无限循环
断言<assert.h>
声明某种东西应该为真
void assert(int expression);
执行的时候对参数进行检测, 如果为假, 就向标准错误打印一条诊断信息然后终止程序
1 #include <stdio.h> 2 #include <assert.h> 3 4 int main(void) 5 { 6 assert(0); 7 printf("hi\n"); 8 return 0; 9 } a.out: main5.c:6: main: Assertion `0' failed. 已放弃 (核心已转储)
可以通过这个来检查必须为正确的参数
如果要去除所有的
#define NDEBUG//必须在包含头文件之前
环境<stdlib.h>
由编译器定义的一个列表
char *getenv(char const *name);
根据名字返回一个对应的字符串
执行系统命令<stdlib.h>
void system(char const *command);
实际的调用和编译器有关, 可以使用NULL来检测是否存在
排序查找
在数组之中以升序对数据进行排列, 和类型无关,数组元素的长度固定
void qsort(void *base, size_t n_elements, size_t el_size, int (*compare)(void const *, void const *))
base
要排列的数组
n_elements
元素的数量
el_size
每个元素的大小第四个:函数的比较用的函数,返回一个整数, 大于零, 等于零, 小于零, 分别是第一个参数大于第二个, 等于, 小于
-
查找已经排序的数列
void *bsearch(void const *key, void const *base, size_t n_elements, size_t el_size, int (*compare)(void const *, void const *))
key
要查找的值函数: 一样的话返回0
返回: 查找的指针
locale
为了让函数语言更加的通用,定义了一组特定的参数,每个国家的各不相同
char *setlocale(int category, char const *locale);
category
要修改的部分, 第二个为NULL的时候,返回一个指向对应的指针,可以在之后用来复原, 不是的时候指定新的locale, 成功的话返回的是新的值的指针
值 | 修改 |
---|---|
LC_ALL | 整个local |
LC_COLLATE | 对照序列,影响strcoll,strxfrm 函数 |
LC_CTYPE | 定义于ctype.h 中的函数使用的字符类型分类信息 |
LC_MONETARY | 格式化货币使用的字符 |
LC_NUMERIC | 格式化非货币使用的字符串, 修改格式化输入输出函数和字符串转换函数所使用的小数点符号 |
LC_TIME | strftime 函数的行为 |
货币格式
struct lconv *localeconv(void);
locale
作用
-
字符集增加参数
-
打印方向
-
小数点符号
如果改变了字符集,比较字符串
int strcoll(char const *s1, char const *s2);//进行比较,但需要更多计算 int strxfrm(char *s1, char const *s2, size_t);//简化计算,把字符串(参数2)转换,再用上面的函数比较