1. 输入与输出 <stdio.h>
1.1 文件操作
FILE *fopen(const char *filename, const char *mode)
函数功能:
打开文件,一次最多可打开 FOPEN_MAX 多个文件。
参数:
filename:指定打开的文件,限定为 FILENAME_MAX 多个字符
mode:访问模式
返回值:
"r" 打开文本文件用于读 "w" 创建文本文件用于写,并删除已经存在的内容(如果有的话) "a" 追加;打开或创建文本文件,并向文件末尾追加内容 "r+" 打开文本文件用于更新(即读和写) "w+" 创建文本文件用于更新,并删除已经存在的内容(如果有的话) "a+" 追加;打开或创建文本文件用于更新,写文件时追加到文件末尾 "b" 表示对二进制文件进行操作 文本文件与二进制文件的区别
一个与指定文件相关联的流。如果打开操作失败,则返回NULL。
FILE *freopen(const char *filename, const char *mode, FILE *stream)
函数功能:
以mode指定的模式,打开filename指定的文件,并将该文件关联到stream指定的流。
一般用于改变与标准流(stdin、stdout、stderr)相关联的文件。
参数:
filename、mode:同fopen函数
stream:指定打开文件关联的流
返回值:stream,若出错,则返回NULL。
int fflush(FILE *stream)
函数功能:
对输出流来说,fflush将已经写到缓冲区但还未写入文件的所有数据写入到文件中。
对输入流来说,结果未定义。
参数:
stream:操作的流。传入NULL,表示清洗所有的输出流。
返回值:
0:执行成功
EOF:写的过程中发生错误
int fclose(FILE *stream)
函数功能:
将所有未写入的数据写入stream中,丢弃缓冲区中所有未读输入数据,并释放自动分配的全部缓冲区,最后关闭流。
参数:
stream:操作的流。
返回值:
0:执行成功
EOF:出错
int remove(const char *filename)
函数功能:
删除文件。
参数:
filename:期望删除的文件名称。
返回值:
0:执行成功
非0:执行失败
int rename(const char *oldname, const char *newname)
函数功能:
修改文件名。
如果oldname与newname指定的路径不同,则在修改文件名的同时,移动文件位置。
参数:
oldname:修改前的文件名,带路径
newname:修改后的文件名,带路径
返回值:
0:执行成功
非0:执行失败
FILE *tmpfile(void)
函数功能:
以"wb+"模式创建一个临时文件,该文件在被关闭或程序结束时自动删除。
参数:无
返回值:
执行成功返回一个流,执行失败返回NULL。
char *tmpnam(char str[L_tmpnam])
函数功能:
生成并返回一个临时文件名,该文件名之前是不存在的。最多能确保生成TMP_MAX个不同的名字。
参数:
str:指向字符数组的指针,其中至少要有L_tmpnam(标准库中的宏)个空间。用于存储生成的临时文件名。可以为NULL,此时函数只返回,不存储。
返回值:
一个指向 C 字符串的指针,该字符串存储了临时文件名。
如果 str 是一个空指针,则返回的指针指向一个内部缓冲区,缓冲区在下一次调用函数时被覆盖。
如果 str 不是一个空指针,则返回 str。
如果函数未能成功创建可用的文件名,则返回一个空指针。
1.2 格式化输出
int fprintf(FILE *stream, const char *format, ...)
函数功能:
按照format说明的格式对输出进行转换,并写到stream流中。
返回值:
返回实际写入的字符数,如果失败则返回一个负值。
int printf(const char *format, ...)
函数功能:
等价于fprintf(stdout, ...)。
int sprintf(char *str, const char *format, ...)
函数功能:
与printf基本相同,但其输出将被写入到字符串str中,并以'\0'结尾。str必须足够大,以容纳下输出结果。
返回值:
返回实际输出的字符数,不包括'\0'。
int vprintf(const char *format, va_list arg)
int vfprintf(FILE *stream, const char *format, va_list arg)
int vsprintf(char *str, const char *format, va_list arg)
函数功能:
这三个函数分别与对应的printf函数等价,但它们用arg代替了可变参数表。
1.3 格式化输入
int fscanf(FILE *stream, const char *format, ...)
函数功能:
根据格式串format从流stream中读取输入,并把转换后的之赋值给后续的参数,其中每个参数都必须是一个指针。
返回值:
当格式串用完时,函数返回,如果到达函数的末尾,或在转换输入前出错,函数返回EOF;否则,返回实际被转换并赋值的输入项的数目。
int scanf(const char *format, ...)
函数功能:
等价于fscanf(stdin, ...)。
int sscanf(const char *str, const char *format, ...)
函数功能:
与scanf基本相同,但其输入来源于字符串str。
1.4 字符输入/输出函数
int fgetc(FILE *stream) //返回流stream的下一个字符,返回类型为unsigned char(被转换为int类型)。如果到达文件末尾或发生错误,返回EOF。
int getc(FILE *stream) //等价于fgetc。不同的是,当getc定义为宏,它可能多次计算stream的值。
int getchar() //等价于getc(stdin)。
int fputc(int c, FILE *stream) //把字符c(转换为unsigned char类型)输出到流stream中,返回输出的字符本身,若出错则返回EOF。
int putc(int c, FILE *stream) //等价于fputc。不同的是,当putc定义为宏,它可能多次计算stream的值。
int putchar() //等价于putc(c, stdout)。
char *fgets(char *s int n, FILE *stream) //从stream流中读取最多n-1个字符到数组s中。当遇到换行符时读入换行符然后终止读取过程。数组s以'\0'结尾。函数返回数组s。如果到达文件末尾或发生错误,则返回NULL。
int fputs(const char *s, FILE *stream) //将字符串s(不包含'\n'字符)输出到stream流中,返回一个非负值,若出错则返回EOF。
char *gets(char *s) //从stdin读入下一个输入行到数组s中,并把末尾的'\n'替换为'\0'。返回数组s。如果到达文件末尾或发生错误,则返回NULL。
int puts(const char *s) //将字符串s和一个换行符输出到stdout中,返回一个非负值,若出错则返回EOF。
int ungetc(int c, FILE *stream) //将c(转换为unsigned char类型)写回到stream流中。下次对该流进行读操作时,将返回该字符。对每个流只能写回一个字符,且该字符不能是EOF。返回被写回的字符,如果发生错误,则返回EOF。该函数并不真正修改文件,而是临时改变流的下个读出字符。
1.5 直接输入输出函数
size_t fread(void *ptr, size_t size, size_t nobj, FILE *stream)
函数功能:
从stream流中读入最多nobj个长度为size的对象,并保存到ptr指向的内存中。
必须通过函数feof和ferror获得结果执行状态。
返回值:
实际读取的对象数目,可能小于nobj。
size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *stream)
函数功能:
从ptr指向的数组中读取nobj个长度为size的对象,写入到stream流中。
返回值:
实际写入的对象数目,如果发生错误,返回值会小于nobj。
1.6 文件定位函数
int fseek(FILE *stream, long offset, int origin)
函数功能:
设置stream流的文件位置为origin(SEEK_SET 文件开头、 SEEK_CUR 当前位置、 SEEK_END文件末尾)开始的第offset(可以为负数)个字符处,后续的读写操作将从新位置开始。
返回值:
正常0,出错非0。
long ftell(FILE *stream) //返回stream流的当前位置,出错返回-1L
void rewind(FILE *stream) //将stream流的位置设置到文件开头
int fgetpos(FILE *stream, fpos_t *ptr) //将stream流的当前位置记录在*ptr中,出错返回非0
int fsetpos(FILE *stream, fpos_t *ptr) //将stream流的当前位置设置为fgetpos函数记录在*ptr中的值,出错返回非0
1.7 错误处理函数
void clearerr(FILE *stream) //清除与流stream相关的文件结束符与错误指示符
int feof(FILE *stream) //如果设置了与流stream相关的文件结束指示符,feof将返回一个非0值
int ferror(FILE *stream) //如果设置了与流stream相关的错误指示符,ferror将返回一个非0值
void perror(const char *s) //打印字符串s以及整形值errno对应的错误描述信息,类似于:fprintf(stderr, "%s: %s\n", s, "errno message")
2. 字符类别测试 <ctype.h>
int isupper(int c) //c是大写字母
int islower(int c) //c是小写字母
int isalpha(int c) //c是大写字母或小写字母
int isdigit(int c) //c是十进制数字
int isxdigit(int c) //c是十六进制数字
int isalnum(int c) //c是大写字母或小写字母或十进制数字
int iscntrl(int c) //c是控制字符
int ispunct(int c) //c是除空格、字母和数字外的可打印字符
int isgraph(int c) //c是除空格外的可打印字符
int isprint(int c) //c是包括空格的可打印字符
int isspace(int c) //c是空格、换页符、换行符、回车符、横向制表符或纵向制表符
函数功能:
判断c是否满足指定条件。
说明:在7位ASCII字符集中,可打印字符是从0x20(' ')到0x7E('~')之间的字符;控制字符是从0(NUL)到0x1F(US)之间的字符以及字符0x7F(DEL)。
int tolower(int c) //字母转小写
int toupper(int c) //字母转大写
函数参数:
c:必须是EOF或可用unsigned char类型表示的字符。
返回值:
c满足指定条件,返回非0值(表示真),否则返回0(表示假)。
3. 字符串处理 <string.h>
3.1 str...
//str
//拷贝
char* strcpy(char* s, const char* ct) //将字符串ct复制到字符串s中,ct中直到遇到'\0'才认为结束(复制'\0')。返回s。不做任何检查直接复制,如果ct长度大于s的容量,会内存越界(末尾的'\0'越界也是越界)。
char* strncpy(char* s, const char* ct, size_t n) //将字符串ct中最多前n个字符复制到字符串s中,ct中如果提前遇到'\0'则立即停止复制(复制'\0'),不足n个字符的部分,全部用'\0'填充。返回s。如果s容量不足n,会内存越界。
//连接
char* strcat(char* s, const char* ct) //将字符串ct连接到s的尾部,覆盖s末尾原本的'\0',ct中直到遇到'\0'才认为结束(连接'\0')。返回s。不做任何检查,如果连接占用的长度超出了s的容量,会内存越界(末尾的'\0'超出也是越界)。
char* strncat(char* s, const char* ct, size_t n) //将字符串ct中最多前n个字符连接到s的尾部,覆盖s末尾原本的'\0',ct中如果提前遇到'\0'则立即停止(连接'\0'),不足n个字符的部分,不做处理。返回s。如果连接占用的长度超出了s的容量,会内存越界(末尾的'\0'超出也是越界)。
//比较
int strcmp(const char* cs, const char* ct) //比较两个字符串,一直比到'\0'。当cs==ct时,返回0;当cs>ct时,返回一个正数;当cs<ct时,返回一个负数。
int strncmp(const char* cs, const char* ct, size_t n) //将字符串cs中最多前n个字符与字符串ct做比较,遇到'\0'时也会做比较。当cs==ct时,返回0;当cs>ct时,返回一个正数;当cs<ct时,返回一个负数。
//搜索
char* strchr(const char* cs, int c) //返回 指向 字符c在字符串cs中第一次出现的位置 的指针,如果cs不包含c,返回NULL
char* strrchr(const char* cs, int c) //返回 指向 字符c在字符串cs中最后一次出现的位置 的指针,如果cs不包含c,返回NULL
char* strstr(const char* cs, const char* ct) //返回一个指针,指向字符串ct在字符串cs中第一次出现的位置,如果不出现,返回NULL
char* strpbrk(const char* cs, const char* ct) //返回一个指针,指向字符串cs中的第一个在ct中包含的字符,如果cs中任意字符都不在ct中存在,返回NULL
//长度
size_t strlen(const char* cs) //返回字符串cs的长度,遇'\0'结束,不包括'\0'
size_t strspn(const char* cs, const char* ct) //返回字符串cs的一个前缀的长度,该前缀中的每个字符都在字符串ct中存在
size_t strcspn(const char* cs, const char* ct) //返回字符串cs的一个前缀的长度,该前缀中的每个字符都在字符串ct中不存在
char* strerror(size_t n) //返回一个指针,指向与错误编号n对应的错误信息字符串(内容与具体实现相关)
char* strtok(char* s, const char* ct) //用于分割字符串s,字符串ct是分割符的集合。
//具体使用时:
//首次调用strtok,入参s不能为NULL,第二次及以后的调用中,入参s需要为NULL。
//每一次调用,返回 指向 被分割出的一个子串 的指针,并将当前子串后的一个分割符置为'\0',下次调用返回 指向 下一个子串 的指针,分割符操作类推,当在也没有子串时,返回NULL。
//整个过程结束,s中存在的分割符全部或部分会被替换为'\0'。
3.2 mem...
//mem 按照字符数组的方式操作对象。
void* memcpy(void* s, const void* ct, size_t n) //将字符串ct中的n个字符拷贝到s中。返回s。
void* memmove(void* s, const void* ct, size_t n) //功能与memcpy类似,不同的是在对象重叠时,memmove仍能正确执行。
int memcmp(const void* cs, const void* ct, n) //将cs的前n个字符与ct比较,返回值同strcmp
void* memchr(const void* cs, int c, size_t n) //返回一个指针,指向c在cs中第一次出现的位置。如果在cs的前n个字符中找不到c,返回NULL。
void* memset(void* s, int c, size_t n) //将s中的前n个字符置为c,返回s。
4. 实用函数 <stdlib.h>
4.1 数值转换
double atof(const char* s) //将字符串s转换为double类型。等价于strtod(s, (char**)NULL)。
int atoi(const char* s) //将字符串s转换为int类型。等价于(int)strtol(s, (char**)NULL, 10)。
long atol(const char* s) //将字符串s转换为long类型。等价于strtol(s, (char**)NULL, 10)。
double strtod(const char* s, char** endp) //跳过字符串s前边的空白,从第一个非空白开始,转换有效范围字符串为double类型。在endp不为NULL的情况下,会将有效范围的下一个位置保存在*endp中。如果转换结果上溢,函数返回带有适当符号的 HUGE_VAL,如果结果下溢,函数返回0。这两种情况下,error都会被置为ERANGE。
long strtol(const char* s, char** endp, int base) //基本功能同strtod,转换的结果是long类型。base代表数制类型。
unsigned long strtoul(const char* s, char** endp, int base) //基本功能同strtol,转换的结果是unsigned long类型。
4.2 随机数
int rand(void) //产生一个0~RAND_MAX之间的伪随机数。RAND_MAX至少为32767。
void srand(unsigned int seed) //将seed作为生成新的伪随机数序列的种子数。种子数seed的初值为1。
4.3 动态内存分配
void* malloc(size_t size) //为长度为size的对象分配内存,返回指向分配区域的指针。分配失败返回NULL。不对分配的内存区域进行初始化。
void* calloc(size_t nobj, size_t size) //为nobj个长度为size的对象组成的数组分配内存,返回指向分配区域的指针。分配失败返回NULL。分配的内存区域被初始化为0。
void* realloc(void* p, size_t size)
//将p指向的对象的长度修改为size。返回指向新分配内存区域的指针。
//重分配成功旧内存会被自动释放,p变成了野指针。
//realloc失败的时候,返回NULL,原来的内存不改变,不会释放也不会移动。
//假如原来的内存后面还有足够多剩余内存的话,realloc的内存=原来的内存+剩余内存,realloc还是返回原来内存的地址。
//假如原来的内存后面没有足够多剩余内存的话,realloc将申请新的内存,然后把原来的内存数据拷贝到新内存里,原来的内存将被free掉,realloc返回新内存的地址。
//如果size为0,效果等同于free(p),这里需要注意的是只对指针本身进行释放,例如对二维指针**a,对a调用realloc时只会释放一维,使用时谨防内存泄露。
//传递给realloc的指针必须是先前通过malloc(), calloc(), 或realloc()分配的。
//传递给realloc的指针可以为NULL,等同于malloc(size)。
void free(void *p) //释放p指向的内存空间。当p为NULL时不执行任何操作。p必须是先前通过malloc(), calloc(), 或realloc()分配的。
4.4 系统相关
void abort(void) //使程序非正常终止
void exit(int status) //使程序正常终止。所有已经打开的文件缓冲区将被清洗,所有已经打开的流将被关闭,控制被返回给环境。status如何返回给环境视情况而定,0值表示终止成功,可以使用EXIT_SUCCESS或EXIT_FAILURE作为返回值。
int atexit(void (*fcn)(void)) //登记函数fcn,该函数将在程序正常终止时被调用(abort不调用,exit会调用)。如果登记失败,返回非0值。 登记的顺序与被调用的顺序相反。
int system(const char *s) //将字符串s传递给执行环境。如果s为NULL且有命令处理程序,则返回非0值。如果s不为NULL,返回值与具体实现相关。
char *getenv(const char *name) //返回与name相关的环境字符串。如果不存在则返回NULL。细节与具体的实现相关。
4.5 排序与查找
void qsort(void *base, size_t n, size_t size,
int (*cmp)(const void *v1, const void *v2) )
函数功能:对数组升序排列。
参数:
base: 要排序的数组
n: 数组元素个数
size: 数组单个元素的字节数
cmp: 函数指针,用于指定排序规则,该函数返回值要求:v1小于v2返回一个负数,v1等于v2返回0,v1大于v2返回一个正数
返回值: 无
//查找
void *bsearch(const void *key, const void *base, size_t n, size_t size,
int (*cmp)(const void *v1, const void *v2) )
函数功能:在数组中查找指定元素。
参数:
key: 要查找的值的地址
base: 要查找的数组,其中的元素必须已经是升序排列(二分查找要求),提前用qsort进行排序即可
n、size、cmp:同qsort函数
返回值:指向数组中匹配元素的指针,如果找不到则返回NULL。
4.6 数学计算
int abs(int n) //返回n的绝对值
long labs(long n) //返回n的绝对值
div_t div(int num, int denom) //计算num/denom的商和余数,并把结果保存在结构类型div_t的两个int类型成员quot和rem中。
ldiv_t ldiv(long num, long denom) //计算num/denom的商和余数,并把结果保存在结构类型ldiv_t的两个long类型成员quot和rem中。
5. 日期与时间 <time.h>
5.1 类型定义
typedef long clock_t;
typedef long long time_t;
#define CLOCKS_PER_SEC ((clock_t)1000)
#define TIME_UTC 1
struct tm //用于保存日历时间的各个构成部分
{
int tm_sec; //从当前分钟开始经过的秒数 [0,59]
int tm_min; //从当前小时开始经过的分钟数 [0,59]
int tm hour; //从午夜开始经过的小时数 [0,23]
int tm_yday; //从1月1日起经过的天数 [0,365]
int tm_mon; //从1月起经过的月数 [0,11]
int tm_year; //从1900年起经过的年数
int tm_wday; //从星期日起经过的天数 [0,6]
int tm_mday; //当月的第几天数 [1,31]
int tm_isdst; //夏令时标记,使用夏令时则该值为正,否则为0。为负代表该信息无效
}
5.2 相关函数
clock_t clock() //返回程序开始执行后占用的处理器时间,单位ms。返回-1代表无法获取处理器时间
time_t time(time_t *tp) //返回当前日历时间(从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数),返回-1代表无法获取日历时间。如果tp不为NULL,则同时将返回值赋值给*tp
double difftime(time_t time2, time_t time1) //返回time2-time1的时间差(秒)
struct tm *gmtime(const time *tp) //将*tp中的时间转换为UTC时间。失败返回NULL。
struct tm *localtime(const time *tp) //将*tp中的时间转换为当地时间。
char *asctime(const struct tm *tp) //将*tp中的时间转换为固定格式[Sun Dec 31 08:43:24 2023]
char *ctime(const time_t *tp) //将*tp中的时间转换为固定格式的当地时间。相当于asctime(localtime(tp))
time_t mktime(struct tm *tp) //将*tp中的时间(作为当地时间)转换为日历时间,失败返回-1
size_t strftime(char *s, size_t smax, const char *fmt, const struct tm *tp)
函数功能: 将*tp中的时间按照fmt中指定的格式存储到s中。smax标识最大写入字符数。
返回值:实际写入s中的字符数,如果字符数多于smax,返回0。
格式字符示例如下:
6. 数学函数 <math.h>
double sin(double x) //x的正弦值
double cos(double x) //x的余弦值
double tan(double x) //x的正切值
double asin(double x) //sin-1(x),值域为[-π/2, π/2],x∈[-1, 1]
double acos(double x) //cos-1(x),值域为[0, π],x∈[-1, 1]
double atan(double x) //tan-1(x),值域为[-π/2, π/2]
double atan2(double y, double x) //tan-1(y/x),值域为[-π, π]
double sinh(double x) //x的双曲正弦值
double cosh(double x) //x的双曲余弦值
double tanh(double x) //x的双曲正切值
double exp(double n) //幂函数 eⁿ
double log(double x) //自然对数ln(x),x>0
double log10(double x) //以10为底的对数log10(x),x>0
double pow(double x, double y) //x的y次方。如果 x=0&&y<=0 或者 x<0&&y不是整型数,将产生定义域错误
double sqrt(double x) //x的平方根,x>=0
double ceil(double x) //x向上取整
double floor(double x) //x向下取整
double fabs(double x) //x的绝对值
double ldexp(double x, int n)
double frexp(double x, int *exp)
double modf(double x, double *ip) //把x分为整数和小数两部分,两部分的正负号均与x相同。返回小数部分,ip存储整数部分
double fmod(double x, double y) // x/y的浮点余数
<complex.h>
todo
7. 可变参数表 <stdarg.h>
va_list ap; //定义变量,ap将依次指向可变参数表中的每个实际参数
va_start(va_list ap, lastarg); //初始化ap(指向可变参数表的第一个参数),lastarg是函数的最后一个有名形式参数(即函数至少要有一个有名形参)
va_arg(ap, 类型名); //每次调用,返回可变参数表中的一个参数,同时将ap指向下一个参数
va_end(ap); //关闭参数列表
提供遍历未知数目和类型的函数参数表的功能(函数至少要有一个确定的参数)。
va_list是类型。va_start、va_arg、va_end是宏定义。
<stdalign.h>
<stdatomic.h>
8. 断言 <assert.h>
void assert(int 表达式)
assert宏用于为程序增加诊断功能。
在debug模式下生效,release模式(定义了NDEBUG宏)下忽略。
如果入参表达式的值为非0,不采取任何操作,否则,会在stderr中打印错误信息,并包含位置信息。比如:“Assertion failed:0,file源文件名,line行号”。
9. 非局部跳转 <setjmp.h>
10. 信号 <signal.h>
11. 与具体实现相关的限制 <limits.h> <float.h>
<stdbool.h>
<stdint.h>
<inttypes.h>
<fenv.h>
<stddef.h>
<errno.h>
<locale.h>
<stdnoreturn.h>
<tgmath.h>
<uchar.h> <wchar.h> <wctype.h>
<iso646.h>
<threads.h>