Appearance
标准库函数
整形函数
分为三类
- 算数
- 随机数
- 字符串转换
算数<stdlib.h>
C
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>
C
int rand(void);
void srand(unsignde int seed);
rand
返回一个范围在0到RAND_MAX的随机数,至少为32767
srand
设置随机数srand((unsigned int)time(0));
设置为时间
字符串转换<sdlib.h>
C
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
C
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
三角函数
C
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的值求反正切的值,通过两个数的符号决定象限,返回值为-π-π
双曲函数
C
double sinh(double angle);
double cosh(double angle);
double tanh(double angle);
对数指数函数
C
double exp(double x);
double log(double x);
double log10(double x);
exp返回e的x次幂
log返回log以x的底数
log10以10为底数
浮点数表示
根据编译器格式存储一个浮点数
C
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
把一个小数分解为两部分,整数部分存储以第二个参数,小数部分返回值
幂
C
double pcw(double x, double y);
double sqrt(double x);
pcw
返回x的y次幂x^y,如果x是一个负数,y不是一个整数就会出现定义域错误
sqrt
函数返回参数的平方根,为负数出现定义域错误
底数、顶数、绝对值和余数
C
double floor(double x);
double cell(double x);
double fabs(double x);
double fmod(double x, double y);
floor
返回不大于这个数的最大整数
cell
返回不小于的最小值
fabs
返回其参数的绝对值
fmod
返回x除以y的余数
字符转转换
C
double atof(char const *string);
double strtod(char const *string, char **unused);
参数前有空白直接忽略,然后把合法的字符转换为一个double,忽略结尾的非法字符
strtod
会返回一个指向下一个参数的指针
没有合法的参数返回0,如果过大存储不下
errno
存储ERANGE这个值函数返回HUGE_VAL
日期和时间函数
处理时间<time.h>
C
clock_t clock(void);
这个值可能是一个近似值,如果要更精确的值,可以再main函数最开始调用,然后用两个数相减,如果机器不能提供时间,或者时间太大返回-1,程序开始执行到调用这个函数的时间
返回的是一个数字,是处理器滴答的次数, 转换为秒应该除以常量CLOCK_PER_SEC
当天时间
time_t time(time_t *retrun_value);
返回的时间通过这个指针传递, 时间太大的话返回-1,标准没有定义具体的格式,最好不要直接使用
时间日期的转换
C
char *ctime(time_t const *time_value);
double difftime(time_t time_t time2);
ctime
的参数是一个指向time_t的指针,返回的是一个字符串格式
C
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的值,把结果转换为秒
C
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 | 夏令时标志 |
C
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
- 结构体的操作
C
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 | 时区简写 |
C
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
C
time_t mktime(struct tm *tm_ptr);
把结构体转换为size_t格式
非本地跳转<setjmp.h>
类似于goto
但是范围不限于一个函数的作用域之内,常用于深层函数嵌套链
C
int setjmp(jmp_buf state);
void longjmp(jump_buf state, int value);
声明一个
jmp_buf
的变量,使用setjmp对他初始化,返回值为0,同时把程序的状态进行保存,调用时候的函数成为顶层函数,之后使用longjmp
函数进行返回
longjmp
就是通过让执行流,通过再次从setjump返回,返回值是value,必须为一个非零的值
C
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>
C
int raise(int sig);
可以主动引发一个信号,和自助引发的作用一样
C
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
数据
信号的处理可能会发生在任何时候, 要处理的变量可能会在任何时候发生改变, 这个关键字告诉编译器防止他修改程序含义的方式优化程序
示例
C
if(value){
printf("True");
}
else{
printf("False");
}
if(value){
printf("True");
}
else{
printf("False");
}
可能会被优化为
C
if(value){
printf("True");
printf("True");
}
else{
printf("False");
printf("False");
}
但是由于信号可能在任何时候产生, 所以有可能导致结果的不同
信号处理函数返回
从信号处理函数返回到信号发生的地方, 例外是SIGFPE(计算出错),由于计算不能完成, 结果未知
如果希望再次捕捉同样的信号, 要在返回之前用
signal
函数重新设置
由于不同的机器处理方式不同, 有可能不会定义所有的符号, 有的也不会回到缺省的状态, 所以移植姓会降低
打印可变参数列表<stdarg.h>
C
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>
C
void abort(void);
void atexit(void (func)(void));
void exit(int status);
abort
不正常的终止一个正在运行的程序,引发信号
atexit
用来把一些函数注册为退出函数.当函数正常终止的时候用(exit
或者main
的return
),退出函数被调用,有多个的时候按照注册的顺序依次执行
exit调用之后注册的函数依次调用, 然后用于流的缓冲区刷新,所有打开的文件关闭,
tmpfile
创建的文件删除
- **注:**在注册的函数之中调用exit有可能会导致无限循环
断言<assert.h>
声明某种东西应该为真
C
void assert(int expression);
执行的时候对参数进行检测, 如果为假, 就向标准错误打印一条诊断信息然后终止程序
C
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.
已放弃 (核心已转储)
可以通过这个来检查必须为正确的参数
如果要去除所有的
C#define NDEBUG//必须在包含头文件之前
环境<stdlib.h>
由编译器定义的一个列表
C
char *getenv(char const *name);
根据名字返回一个对应的字符串
执行系统命令<stdlib.h>
C
void system(char const *command);
实际的调用和编译器有关, 可以使用NULL来检测是否存在
排序查找
在数组之中以升序对数据进行排列, 和类型无关,数组元素的长度固定
C
void qsort(void *base, size_t n_elements, size_t el_size, int (*compare)(void const *, void const *))
base
要排列的数组
n_elements
元素的数量
el_size
每个元素的大小第四个:函数的比较用的函数,返回一个整数, 大于零, 等于零, 小于零, 分别是第一个参数大于第二个, 等于, 小于
- 查找已经排序的数列
C
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
为了让函数语言更加的通用,定义了一组特定的参数,每个国家的各不相同
C
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 函数的行为 |
货币格式
C
struct lconv *localeconv(void);
locale
作用
- 字符集增加参数
- 打印方向
- 小数点符号
如果改变了字符集,比较字符串
C
int strcoll(char const *s1, char const *s2);//进行比较,但需要更多计算
int strxfrm(char *s1, char const *s2, size_t);//简化计算,把字符串(参数2)转换,再用上面的函数比较