C语言学习笔记(更新中)
字符串函数
这些str开头的函数均包含在string.h
头文件中
strlen(const char*str)
用于统计字符串的长度strcat(char*str1,const char*str2)
将str2拼接在str1后,返回值是拼接第二个字符串后第一个字符串的地址strncat(char*str1,const char*str2,size_t n)
解决了strcat中分配给str1的空间不够大,溢出到相邻存储单元的问题。第三个参数指定了最大添加字符数strcmp(const char*str1,const char*str2)
比较字符串,返回0时字符串相等,>0时str1>str2,<0时str1<str2strncmp(const char*str1,const char*str2,size_t n)
可以限定只查比较n个字符strcpy(const char*str1,const char*str2)
将str2复制到str1strncpy(const char*str1,const char*str2,size_t n)
第三个参数指明可拷贝的最大字符数sprintf(char*str,const char*format,……)
其声明在stdio.h中而非string.h,与printf类似,但是其是把数据写入字符串(第一个参数)strchr(const char*s,int c)
若s字符串包含c字符,则返回s首次出现c的指针,未找到则返回空指针strrchr(const char*s,int c)
若s字符串包含c字符,则返回s最后一次出现c的指针,未找到则返回空指针strstr(const char*s1,const char*s2)
若s1字符串包含s2字符串,则返回s1首次出现s2的指针,未找到则返回空指针strpbrk(const char*s1,const char*s2)
若s1字符串包含s2字符串中的任意字符,则返回s1首次出现s2中任意字符的指针,未找到则返回空指针atoi(const char*s)
将字符串转换为整数(字符串’23’->数字23)memset(void *ptr, int value, size_t num)
用于将一段内存区域填充为指定的值memcpy(void* destination, const void* source, size_t num)
用于复制内存块中的内容(注:内存重叠时对其来说是未定义行为)memmove(void *dest, const void *src, size_t n)
memmove与memcpy功能类似,核心区别在于:memmove能够正确处理源内存块和目标内存块重叠的情况
I/O函数
getchar()
从标准输入 stdin 获取一个无符号字符,返回值为该字符的ASCII码值putchar()
打印其参数getc(FILE *stream)
从给定的输入流中读取一个无符号字符,返回值为该字符的ASCII码值putc(int char, FILE *stream)
将指定的字符(一个无符号字符)写入到指定的流中puts(const char*str)
只显示字符串,且在显示的字符串末尾自动添加换行符gets(char*str)
其读取整行输入,直到遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符末尾添加空字符使其成为一个C字符串(其不会检查数组的长度,可能会导致缓冲区溢出,C11标准已废除该函数)fgets(char*str,int n,FILE*stream)
其通过第二个参数限制读入的字符数,设置的值为n,则其将读入n-1个字符,或读到遇到的第一个换行符为止。其读取到换行符时会将其储存在字符串中。第三个参数指明要读入的文件,标准输入使用stdin即可fputs(const char*str,FILE*stream)
其不会像puts函数那样在输出字符串末尾加上换行符gets_s(char*str,rsize_t n)
只要输入行未超过最大字符数,其与gets几乎一样自定义
s_gets
函数原型:
1 | char *s_gets(char *st, int n) |
文件I/O相关
fopen(const char*filename,const char*mode)
打开文件,第一个参数是文件名,第二个参数是打开模式,返回值为文件指针打开模式:
- r 只读
- w 写入,若文件不存在则创建,若文件存在则清空
- a 追加,若文件不存在则创建,若文件存在则从文件末尾开始写入
- r+ 读写,若文件不存在则报错
- w+ 写读,若文件不存在则创建,若文件存在则清空
- a+ 写读,若文件不存在则创建,若文件存在则从文件末尾开始写入
fclose(FILE*stream)
关闭文件,返回值为0表示成功关闭fprintf(FILE*stream,const char*format,……)
将数据写入文件,与printf类似fscanf(FILE*stream,const char*format,……)
从文件中读取数据,与scanf类似fseek(FILE*stream,long int offset,int origin)
移动文件指针,第一个参数是文件指针,第二个参数是偏移量,第三个参数是偏移的起始位置,返回值为0表示成功移动ftell(FILE*stream)
返回文件指针相对于文件开头的偏移量
储存类别
C语言的“对象”:储存数据的一块内存,标识符用于访问对象
可用存储期描述对象,用作用域和链接描述标识符
作用域:程序中可以访问对象的区域,其分为块作用域、函数作用域、函数原型作用域和文件作用域。
- 块作用域:用花括号括起来的代码块,如函数体、复合语句(即花括号括起来的代码块)
- 函数作用域:函数名的作用域是整个函数体
- 函数原型作用域:函数参数的作用域是函数原型
- 文件作用域: 变量定义在函数的外面(文件作用域变量即为全局变量)
链接:其分为内部链接、外部链接和无链接,非文件作用域的变量均为无连接变量。
- 内部链接:变量只能在其定义所在的文件中访问,其定义以static开头
- 外部链接:变量可以在其定义所在的文件中访问,也可以在其他文件中访问,其定义不以static开头
存储期:其分为自动存储期、静态存储期、线程存储期和动态分配存储期。
- 自动存储期:块作用域的变量通常具有自动存储期,其存储期从进入作用域开始,到离开作用域结束
- 静态存储期:文件作用域的变量具有静态存储期,其存储期从程序开始到程序结束
- 线程存储期:线程作用域的变量具有线程存储期,其存储期从线程开始到线程结束
- 动态分配存储期:动态分配的变量具有动态分配存储期,其存储期从调用malloc函数开始,到调用free函数结束
各种变量类型
- 自动变量:具有自动存储期的变量,其存储期从进入作用域开始,到离开作用域结束,可显式使用关键字
auto
(存储类别说明符)。在内层块中使用与外层块同名的变量,则内层块中的变量会隐藏外层块中的变量 - 寄存器变量:可使用关键字
register
(存储类别说明符)。寄存器变量通常用于存储频繁访问的变量,以提高程序性能。但是,编译器会根据具体情况决定是否将变量存储在寄存器中。 - 块作用域的静态变量:具有静态存储期的变量,其存储期从程序开始到程序结束,使用关键字
static
(存储类别说明符)。块作用域的静态变量在程序执行期间一直存在,即使离开了其定义的作用域,其值也不会被销毁。 - 外部链接的静态变量:其具有文件作用域、外部链接和静态存储期。可通过
extern
关键字在其他文件中访问该变量。 - 内部链接的静态变量:其具有文件作用域、内部链接和静态存储期。通过
extern
关键字在其他文件中访问不到该变量。 const
类型限定符:用于声明常量,其值在程序执行期间不能被修改。volatile
类型限定符:告知计算机代理(共享数据的其他线程)可以改变该变量的值,用于多线程编程,是计算机不要错误地优化。可同时用const和volatile声明一个变量,表示该变量是一个不能被优化且可能被其他线程修改的常量。restirict
类型限定符:用于声明指针,表示该指针指向的内存区域只能被该指针访问(访问数据对象唯一且初始的方式),不能被其他指针访问。用于防止指针被误用,提高程序的安全性。_Atomic
类型限定符:用于声明原子类型,其值在多线程编程中不会被其他线程修改。
随机数函数
rand()
返回一个0~RAND_MAX之间的随机数srand(unsigned int seed)
设置随机数种子,若不设置,则默认为1
在定义这两个函数的头文件中,seed
参数作为内部链接的静态变量存在,rand()
和srand()
都可以访问到它,但是其他文件中的函数则不能。
使用time.h
中的time()
函数作为随机数种子时要注意将time_t类型的返回值强制转换为unsigned int类型。
内存分配
声明变量时会自动分配内存,还可通过malloc()
函数动态分配内存,其声明在stdlib.h中。
该函数接受一个参数:所需的内存字节数。其会找到合适的空闲内存块,这样的内存是匿名的,即malloc()
不为分配的内存赋名,但其返回值为所分配其内存块的首地址,可将其赋给指针变量,然后通过指针变量访问该内存块。当分配内存的类型不为字节时,通过强制类型转换即可,其能达到和变长数组类似的效果
使用示例:
1 | int *ptr = (int*)malloc(10*sizeof(int)); |
若malloc()
无法找到合适的内存块,则返回空指针。
malloc()
分配的内存块在程序结束时不会自动释放,需要使用free()
函数释放,使内存归还于内存池中,否则会出现内存泄漏。
使用示例:
1 | free(ptr); |
free()
函数接受一个参数:指向要释放的内存块首地址的指针。当指针指向的内存块被释放后,指针的值将变为空指针,因此在使用该指针前,最好将其赋值为空指针。
calloc()
接受两个参数:元素个数和每个元素的字节数,其会分配一块内存,并将所有字节都初始化为0,返回值为指向该内存块首地址的指针。
ctype.h系列
字符测试函数
isalnum()
字母或数字isalpha()
字母isblank()
标准的空白字符或被本地化指定为空白的字符iscntrl()
控制字符isdigit()
数字isgraph()
除空格外的任意可打印字符islower()
小写字符isprint()
可打印字符ispunct()
标点符号isspace()
空白字符或被本地化指定为空白的字符isupper()
大写字母isxdigit()
十六进制数字符
如果是对应参数,则返回1
字符串函数
strlen(const char*str)
计算字符串的长度,不包括末尾的空字符,返回值为字符串长度
字符映射函数
tolower()
若参数是大写字符,则返回小写字符;否则返回原参数toupper()
若参数是小写字符,则返回大写字符;否则返回原参数
布尔值
布尔值使用_Bool
作为类型名,该变量只能存储1或0,若把其他非0值赋给该类型,则该变量设置为1
若使用stdbool.h
头文件,即可用bool
代替_Bool
作为别名,且把true
定义为false
分别定义为1和0的符号常量,以和C++兼容
复合字面量
复合字面量是匿名的,所以不能先创建再使用,必须在创建的同时使用它。
使用示例:
1 | int * ptr; //定义指针 |