字符串函数

这些str开头的函数均包含在string.h头文件中

  1. strlen(const char*str) 用于统计字符串的长度
  2. strcat(char*str1,const char*str2) 将str2拼接在str1后,返回值是拼接第二个字符串后第一个字符串的地址
  3. strncat(char*str1,const char*str2,size_t n) 解决了strcat中分配给str1的空间不够大,溢出到相邻存储单元的问题。第三个参数指定了最大添加字符数
  4. strcmp(const char*str1,const char*str2) 比较字符串,返回0时字符串相等,>0时str1>str2,<0时str1<str2
  5. strncmp(const char*str1,const char*str2,size_t n) 可以限定只查比较n个字符
  6. strcpy(const char*str1,const char*str2) 将str2复制到str1
  7. strncpy(const char*str1,const char*str2,size_t n) 第三个参数指明可拷贝的最大字符数
  8. sprintf(char*str,const char*format,……) 其声明在stdio.h中而非string.h,与printf类似,但是其是把数据写入字符串(第一个参数)
  9. strchr(const char*s,int c) 若s字符串包含c字符,则返回s首次出现c的指针,未找到则返回空指针
  10. strrchr(const char*s,int c) 若s字符串包含c字符,则返回s最后一次出现c的指针,未找到则返回空指针
  11. strstr(const char*s1,const char*s2) 若s1字符串包含s2字符串,则返回s1首次出现s2的指针,未找到则返回空指针
  12. strpbrk(const char*s1,const char*s2) 若s1字符串包含s2字符串中的任意字符,则返回s1首次出现s2中任意字符的指针,未找到则返回空指针
  13. atoi(const char*s) 将字符串转换为整数(字符串’23’->数字23)
  14. memset(void *ptr, int value, size_t num)用于将一段内存区域填充为指定的值
  15. memcpy(void* destination, const void* source, size_t num)用于复制内存块中的内容(注:内存重叠时对其来说是未定义行为)
  16. memmove(void *dest, const void *src, size_t n)memmove与memcpy功能类似,核心区别在于:memmove能够正确处理源内存块和目标内存块重叠的情况

I/O函数

  1. getchar() 从标准输入 stdin 获取一个无符号字符,返回值为该字符的ASCII码值

  2. putchar() 打印其参数

  3. getc(FILE *stream) 从给定的输入流中读取一个无符号字符,返回值为该字符的ASCII码值

  4. putc(int char, FILE *stream) 将指定的字符(一个无符号字符)写入到指定的流中

  5. puts(const char*str) 只显示字符串,且在显示的字符串末尾自动添加换行符

  6. gets(char*str) 其读取整行输入,直到遇到换行符,然后丢弃换行符,储存其余字符,并在这些字符末尾添加空字符使其成为一个C字符串(其不会检查数组的长度,可能会导致缓冲区溢出,C11标准已废除该函数)

  7. fgets(char*str,int n,FILE*stream) 其通过第二个参数限制读入的字符数,设置的值为n,则其将读入n-1个字符,或读到遇到的第一个换行符为止。其读取到换行符时会将其储存在字符串中。第三个参数指明要读入的文件,标准输入使用stdin即可

  8. fputs(const char*str,FILE*stream) 其不会像puts函数那样在输出字符串末尾加上换行符

  9. gets_s(char*str,rsize_t n) 只要输入行未超过最大字符数,其与gets几乎一样

  10. 自定义s_gets

    函数原型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
char *s_gets(char *st, int n)  
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if(ret_val) //若指针不为空
{
find = strchr(st, '\n');
if(find)
{
*find = '\0'; //将\n换为\0
}
else
{
while(getchar() != '\n') //将\n后的内容丢弃
continue;
}
}
return ret_val;
}

文件I/O相关

  1. fopen(const char*filename,const char*mode) 打开文件,第一个参数是文件名,第二个参数是打开模式,返回值为文件指针

    打开模式:

    1. r 只读
    2. w 写入,若文件不存在则创建,若文件存在则清空
    3. a 追加,若文件不存在则创建,若文件存在则从文件末尾开始写入
    4. r+ 读写,若文件不存在则报错
    5. w+ 写读,若文件不存在则创建,若文件存在则清空
    6. a+ 写读,若文件不存在则创建,若文件存在则从文件末尾开始写入
  2. fclose(FILE*stream) 关闭文件,返回值为0表示成功关闭

  3. fprintf(FILE*stream,const char*format,……) 将数据写入文件,与printf类似

  4. fscanf(FILE*stream,const char*format,……) 从文件中读取数据,与scanf类似

  5. fseek(FILE*stream,long int offset,int origin) 移动文件指针,第一个参数是文件指针,第二个参数是偏移量,第三个参数是偏移的起始位置,返回值为0表示成功移动

  6. ftell(FILE*stream) 返回文件指针相对于文件开头的偏移量

储存类别

C语言的“对象”:储存数据的一块内存,标识符用于访问对象

可用存储期描述对象,用作用域和链接描述标识符

作用域:程序中可以访问对象的区域,其分为块作用域、函数作用域、函数原型作用域和文件作用域。

  1. 块作用域:用花括号括起来的代码块,如函数体、复合语句(即花括号括起来的代码块)
  2. 函数作用域:函数名的作用域是整个函数体
  3. 函数原型作用域:函数参数的作用域是函数原型
  4. 文件作用域: 变量定义在函数的外面(文件作用域变量即为全局变量)

链接:其分为内部链接、外部链接和无链接,非文件作用域的变量均为无连接变量。

  1. 内部链接:变量只能在其定义所在的文件中访问,其定义以static开头
  2. 外部链接:变量可以在其定义所在的文件中访问,也可以在其他文件中访问,其定义不以static开头

存储期:其分为自动存储期、静态存储期、线程存储期和动态分配存储期。

  1. 自动存储期:块作用域的变量通常具有自动存储期,其存储期从进入作用域开始,到离开作用域结束
  2. 静态存储期:文件作用域的变量具有静态存储期,其存储期从程序开始到程序结束
  3. 线程存储期:线程作用域的变量具有线程存储期,其存储期从线程开始到线程结束
  4. 动态分配存储期:动态分配的变量具有动态分配存储期,其存储期从调用malloc函数开始,到调用free函数结束

各种变量类型

  1. 自动变量:具有自动存储期的变量,其存储期从进入作用域开始,到离开作用域结束,可显式使用关键字auto(存储类别说明符)。在内层块中使用与外层块同名的变量,则内层块中的变量会隐藏外层块中的变量
  2. 寄存器变量:可使用关键字register(存储类别说明符)。寄存器变量通常用于存储频繁访问的变量,以提高程序性能。但是,编译器会根据具体情况决定是否将变量存储在寄存器中。
  3. 块作用域的静态变量:具有静态存储期的变量,其存储期从程序开始到程序结束,使用关键字static(存储类别说明符)。块作用域的静态变量在程序执行期间一直存在,即使离开了其定义的作用域,其值也不会被销毁。
  4. 外部链接的静态变量:其具有文件作用域、外部链接和静态存储期。可通过extern关键字在其他文件中访问该变量。
  5. 内部链接的静态变量:其具有文件作用域、内部链接和静态存储期。通过extern关键字在其他文件中访问不到该变量。
  6. const类型限定符:用于声明常量,其值在程序执行期间不能被修改。
  7. volatile类型限定符:告知计算机代理(共享数据的其他线程)可以改变该变量的值,用于多线程编程,是计算机不要错误地优化。可同时用const和volatile声明一个变量,表示该变量是一个不能被优化且可能被其他线程修改的常量。
  8. restirict类型限定符:用于声明指针,表示该指针指向的内存区域只能被该指针访问(访问数据对象唯一且初始的方式),不能被其他指针访问。用于防止指针被误用,提高程序的安全性。
  9. _Atomic类型限定符:用于声明原子类型,其值在多线程编程中不会被其他线程修改。

随机数函数

  1. rand() 返回一个0~RAND_MAX之间的随机数
  2. 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系列

字符测试函数

  1. isalnum() 字母或数字
  2. isalpha() 字母
  3. isblank() 标准的空白字符或被本地化指定为空白的字符
  4. iscntrl() 控制字符
  5. isdigit() 数字
  6. isgraph() 除空格外的任意可打印字符
  7. islower() 小写字符
  8. isprint() 可打印字符
  9. ispunct() 标点符号
  10. isspace() 空白字符或被本地化指定为空白的字符
  11. isupper() 大写字母
  12. isxdigit() 十六进制数字符
    如果是对应参数,则返回1

字符串函数

  1. strlen(const char*str) 计算字符串的长度,不包括末尾的空字符,返回值为字符串长度

字符映射函数

  1. tolower() 若参数是大写字符,则返回小写字符;否则返回原参数
  2. toupper() 若参数是小写字符,则返回大写字符;否则返回原参数

布尔值

布尔值使用_Bool作为类型名,该变量只能存储1或0,若把其他非0值赋给该类型,则该变量设置为1

若使用stdbool.h头文件,即可用bool代替_Bool作为别名,且把true定义为false分别定义为1和0的符号常量,以和C++兼容

复合字面量

复合字面量是匿名的,所以不能先创建再使用,必须在创建的同时使用它。

使用示例:

1
2
int * ptr;                      //定义指针
ptr = (int [2]){ 10, 20 }; //使指针指向该复合字面量