【教程】Leetcode 必知必会常用函数(C 语言版)
目录
- 常用数据结构的声明,定义和初始化
- 数组
- 数组申请
- 数组赋值
- 指针
- 指针常量和常量指针
- 指针数组与数组指针
- 指针指向二维数组
- 字符串与字符数组
- 初始化
- 常用库包含函数
- 字符串操作
- 字符串长度
- strlen
- 字符串拷贝
- strcpy
- strncpy
- 字符串分割
- strtok
- 字符串追加和拼接
- strcat
- sprintf
- 字符串比较
- strcmp
- strncmp
- 字符串子串
- strchr
- strrchr
- strstr
- 数值字符串转数值型
- strtol
- strtoll
- strtod
- 减 '0'
- 内存处理类
- 内存拷贝
- memcpy
- memmove
- 内存设置
- memset
- 常用封装算法
- 查找
- bsearch
- 排序
- qsort
- 参考
常用数据结构的声明,定义和初始化
数组
数组申请
- 示例
// 一维数组
int* num = (int*)malloc(sizeof(int) * 10);// 二维数组int** num = (int**)malloc(sizeof(int*) * 10); // 为第一行(维)申请空间for (int i = 0; i < 10; i++) {num[i] = (int*)malloc(sizeof(int) * 10); // 为第二行(维)申请空间}
数组赋值
- 循环进行赋值
- memset 赋值
// 对动态申请(堆)的一维数组进行赋值
int* num = (int*)malloc(sizeof(int) * 10);
memset(num, 0, sizeof(int) * 10);// 对栈的一维数组进行赋值
int num[10];
memset(num, 0, sizeof(num));
指针
指针常量和常量指针
- 常量指针:const int* ptr,指向常量的指针,指针所指内容不可以改变,但指针本身可以改变
- 指针常量:int* const ptr,指针类型的常量,指针本身不可改变(不能改变地址),指针所指内容可以改变
- 常量指针常量:const int* const ptr,指针本身和指针所指内容都不可以改变
- 怎么记忆:按顺序读
const *
的结构读作常量指针,* const
的结构读作指针常量
指针数组与数组指针
- 数组指针:int (*p)[n],指向数组的指针
- 指针数组:int *p[n],数组里面放指针
- 怎么记忆:对于数组指针,它落脚点是指针二字,由于 () 和 [] 的优先级位于同一层级(最高级),而结合方向是从左向右,所以 (*p) 被视为一个整体优先计算,所以 (*p) 是一个指针指向数组 [n]
指针指向二维数组
- 示例
int arr[2][3] = {0};
int (*ptr)[3] = arr;
字符串与字符数组
初始化
- 示例
char* str = "hello";char* str1 = {"hello"}; // str与str1等价char str2[] = {"hello"}; // str2与str3,str5,str7等价char str3[] = "hello";char str4[] = {'h', 'e', 'l', 'l', 'o'};char str5[] = {'h', 'e', 'l', 'l', 'o', '\0'};char str6[5] = {"hello"};char str7[6] = {"hello"};printf("str: %s sizeof:%d strlen:%d\n", str, sizeof(str), strlen(str)); // str: hello sizeof:8 strlen:5printf("str1:%s sizeof:%d strlen:%d\n", str1, sizeof(str1), strlen(str1)); // str1:hello sizeof:8 strlen:5printf("str2:%s sizeof:%d strlen:%d\n", str2, sizeof(str2), strlen(str2)); // str2:hello sizeof:6 strlen:5printf("str3:%s sizeof:%d strlen:%d\n", str3, sizeof(str3), strlen(str3)); // str3:hello sizeof:6 strlen:5// 末尾未包含空字符,可能导致未定义行为printf("str4:%s sizeof:%d strlen:%d\n", str4, sizeof(str4), strlen(str4)); // str4:hellohello sizeof:5 strlen:10printf("str5:%s sizeof:%d strlen:%d\n", str5, sizeof(str5), strlen(str5)); // str5:hello sizeof:6 strlen:5// 末尾未包含空字符,可能导致未定义行为printf("str6:%s sizeof:%d strlen:%d\n", str6, sizeof(str6), strlen(str6)); // str6:hellohello sizeof:5 strlen:10printf("str7:%s sizeof:%d strlen:%d\n", str7, sizeof(str7), strlen(str7)); // str7:hello sizeof:6 strlen:5
常用库包含函数
<stdio.h>
- 字符串拼接:sprintf
<string.h>
- 字符串长度:strlen
- 字符串拷贝:strcpy 系列
- 字符串分割:strtok 系列
- 字符串追加:strcat
- 字符串比较:strcmp 系列
- 字符串子串相关:strchr,strstr
- 字符串转数值型:strtol 系列
- 内存拷贝:memcpy,memmove
- 内存设置:memset
<strlib.h>
- bsearch:二分查找
- qsort:快排
字符串操作
字符串长度
strlen
- 描述:计算字符串 str 的长度,直到空结束字符,但不包括空结束字符
- 原型:
size_t strlen(const char *str)
- str:被计算字符串
- 返回值:字符串长度
- 头文件
<string.h>
- 安全版本:-
字符串拷贝
strcpy
- 描述:从 src 拷贝字符串到 dest
- 原型:
char *strcpy(char *dest, const char *src)
- dest:目标数组
- src:源数组
- 返回值:指向 dest 字符串的指针
- 头文件
<string.h>
- 安全版本:
strcpy_s
strncpy
- 描述:从 src 拷贝 n 个字符串到 dest。若 src 长度小于 n,则剩余空间用空字节填充
- 原型:
char *strncpy(char *dest, const char *src, size_t n)
- dest:目标数组
- src:源数组
- n:要拷贝的字符数
- 返回值:指向 dest 字符串的指针
- 头文件
<string.h>
- 安全版本:
strncpy_s
字符串分割
strtok
- 描述:以 delim 为分割点,分割字符串。该方法需要通过循环的方式来打印所有的分割结果,而不是一次性分割完毕。具体来说 strtok 首先找到 str 中第一次 delim 的位置,并将其置为 ‘\0’,返回指向第一个分割出来的字符子串的首地址(指针),然后通过循环(此时 str 置为 NULL),strtok 从 ‘\0’ 的位置继续向后寻找下一个 delim,以此类推。
- 原型:
char *strtok(char *str, const char *delim)
- str:目标字符串
- 若 str 不为
- delim:分隔符
- 返回值:每一次分解出来的子字符串,直到遇到终止符
- str:目标字符串
- 头文件
<string.h>
- 安全版本:
strtok_s
- 注意点
- strtok 会改变原 str
- strtok 无法同时处理两个字符串的分割。例如在一些字符串分割后比较两个子串的大小场景下无法使用该方法
- strtok_r 可以解决 2 的问题,但该函数仅在 Linux 下实现
- 示例
int strtok_test(void)
{char string[] = "Day Day up";char *ret;ret = strtok(string, " ");while(ret != NULL) {printf("%s \n", ret);ret = strtok(NULL, " ");}return 0;
}// 输出
Day
Day
up
字符串追加和拼接
strcat
- 描述:把 src 所指向的字符串追加到 dest 所指向的字符串的结尾
- 原型:
char *strcat(char *dest, const char *src)
- dest:目标数组
- src:源数组
- 返回值:指向 dest 字符串的指针
- 头文件
<string.h>
- 安全版本:
strcat_s
- n 字符版本:
strncat
,strncat_s
sprintf
- 描述:发送格式化输出到 str 所指向的字符串
- 原型:
int sprintf(char *str, const char *format, ...)
- str:输出结果到这个字符串
- format:格式化字符串内容,及包含占位符的字符串
- …:填充占位符的内容
- 返回值
- 成功,返回写入字符数
- 失败,返回负数
- 头文件
<stdio.h>
- 安全版本:
sprintf_s
- 示例
int sprintf_s_test( void )
{char buffer[200], s[] = "computer", c = 'l';int i = 35, j;float fp = 1.7320534f;// Format and print various data:j = sprintf_s( buffer, 200, " String: %s\n", s );j += sprintf_s( buffer + j, 200 - j, " Character: %c\n", c );j += sprintf_s( buffer + j, 200 - j, " Integer: %d\n", i );j += sprintf_s( buffer + j, 200 - j, " Real: %f\n", fp );printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
字符串比较
strcmp
- 描述:把 str1 所指向的字符串和 str2 所指向的字符串进行比较。比较原则是按照字符的 ASCII 进行比较,与字符串长度无关
- 原型:
int strcmp(const char *str1, const char *str2)
- str1:第一个字符串
- str2:第二个字符串
- 返回值
- 返回值 < 0,则 str1 < str2
- 返回值 > 0,则 str1 > str2
- 返回值 = 0,则 str1 = str2
- 头文件
<string.h>
- 安全版本:
strcat_s
strncmp
- 描述:比较 str1 和 str2 前 n 个字符串的大小
- 原型:
int strncmp(const char *str1, const char *str2, size_t n)
- str1:第一个字符串
- str2:第二个字符串
- n:要比较的字符个数
- 返回值
- 返回值 < 0,则 str1 < str2
- 返回值 > 0,则 str1 > str2
- 返回值 = 0,则 str1 = str2
- 头文件
<string.h>
- 安全版本:-
字符串子串
strchr
- 描述:返回第一次在字符串 str 中出现字符 c 的位置
- 原型:
char *strchr(const char *str, int c)
- str:被查找字符串
- c:要查找字符
- 返回值
- 若在字符串 str 中找到字符 c,返回指向该字符的指针
- 未找到,返回 NULL
- 头文件
<string.h>
- 安全版本:-
strrchr
- 描述:返回最后一次(反向的第一次)在字符串 str 中出现字符 c 的位置
- 原型:
char *strrchr(const char *str, int c)
- str:被查找字符串
- c:要查找字符
- 返回值
- 若在字符串 str 中找到字符 c,返回指向该字符的指针
- 未找到,返回 NULL
- 头文件
<string.h>
- 安全版本:-
strstr
- 描述:返回第一次在父串 str_1 中出现子串 str_2 的位置
- 原型:
char *strstr (const char *str_1, const char *str_2)
- str_1:父串
- str_2:子串
- 返回值
- 指向第一次出现子串的位置,或者如果没有找到就返回 NULL
- 子串为空,返回父串
- 头文件
<string.h>
- 安全版本:-
数值字符串转数值型
【注】不建议使用 atoi、atol、atoll、atof,因为出错时,产生未定义行为,且不提供详细的错误描述
strtol
- 描述:把参数 str 所指向的字符串根据给定的 base 转换为一个长整型(long int),base 必须介于 2 和 36(包含)之间,或者是特殊值 0
- 原型:
long int strtol(const char *str, char **endptr, int base)
- str:要转换的字符串
- endptr:存储指向数值后的第一个字符
- base:要转换的进制。若 base 为 0,则根据字符串前缀来判断进制,如 ‘0x’ 和 ‘0X’ 表示 16 进制,‘0’ 表示 8 进制
- 返回值
- 成功,返回长整型
- 失败,返回 0,且置 errno 为 ERANGE(errno 位于 <errno.h> 中),errno 用于判断是否有溢出发生。除了溢出外,失败还可能是因为把不能转换的字符串拿来转换成长整型
- 头文件
<string.h>
- 安全版本:-
strtoll
strtod
减 ‘0’
- 描述:通过将数值字符 - ‘0’ 获取对应的整型。例如,‘9’ - ‘0’ 得到 9
- 示例
int stringToInt(void)
{int num = 0 ;char strInt[] = "123";char *strIntPtr = strInt;while(*strIntPtr != '\0'){num = num * 10 + (*strIntPtr - '0');strIntPtr++;}printf("%d", num); // 123return 0;
}
内存处理类
内存拷贝
memcpy
- 描述:从存储区 str2 复制 n 个字节到存储区 str1
- 原型:
void *memcpy(void *str1, const void *str2, size_t n)
- str1:目标内存
- str2:源内存
- n:要被复制的字节数
- 返回值:指向 str1 的指针
- 头文件
<string.h>
- 安全版本:
memcpy_s
memmove
- 描述:从存储区 str2 复制 n 个字节到存储区 str1。比 memcpy 更安全,解决了内存重叠的问题
- 原型:
void *memmove(void *str1, const void *str2, size_t n)
- str1:目标内存
- str2:源内存
- n:要被复制的字节数
- 返回值:指向 str1 的指针
- 头文件
<string.h>
- 安全版本:
memmove_s
内存设置
memset
- 描述:将内存 str 设置指定的值 c,n 为 c 的字节数
- 原型:
void *memset(void *str, int c, size_t n)
- str:目标内存
- c:设置的值
- n:设置的值的字节数,通常用 sizeof 获取
- 返回值:指向 str 的指针
- 头文件
<string.h>
- 安全版本:
memset_s
常用封装算法
查找
bsearch
- 描述:在有序数组中执行二分查找
- 原型:
void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
- key:要查找的元素
- base:被查找的数组
- nmemb:数组中元素的个数
- size:每个元素的大小(字节大小)
- compar:自定义比较函数
- a < b,返回负值
- a = b,0
- a > b,返回正值
- 返回值
- 成功,返回 base 中匹配元素的指针
- 失败,返回 NULL
- 头文件:
stdlib.h
- 示例:示例源于菜鸟教程
#include <stdio.h>
#include <stdlib.h>// 比较函数,用于 bsearch 查找
int cmpfunc(const void * a, const void * b) {return (*(int*)a - *(int*)b);
}int main() {int values[] = { 5, 20, 29, 32, 63 };int key = 32;int *item;// 计算数组长度size_t array_size = sizeof(values) / sizeof(values[0]);// 使用 bsearch 在数组中查找值 32item = (int*) bsearch(&key, values, array_size, sizeof(int), cmpfunc);// 检查查找结果并输出if (item != NULL) {printf("Found item = %d\n", *item);} else {printf("Item = %d could not be found\n", key);}return 0;
}
排序
qsort
- 描述:用于对数组进行排序,采用的是快速排序算法
- 函数原型:
void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *));
- base:指向排序数组的指针
- nitems:数组中的元素数量
- size:数组中每个元素的大小(以字节为单位)
- compar:自定义的比较函数,是一个函数指针,用于比较数组中的两个元素(数值,字符,字符串)。升序比较的规则如下:
- 第一个元素 > 第二个元素:返回 >0
- 第一个元素 < 第二个元素:返回 <0
- 第一个元素 = 第二个元素:返回 =0
- 返回值:无
- 头文件:
<stdlib.h>
- 示例一:比较数值
int compareNumFunc(const void* a, const void* b) {return (*(int*)a - *(int*)b);
}int compareNum() {int arr[] = {10, 5, 4, 6, 9};int n = sizeof(arr) / sizeof(arr[0]);qsort(arr, n, sizeof(int), compareNumFunc);printf("Following is the sorted array: ");int i;for (i = 0; i < n; ++i) {printf("%d ", arr[i]);}printf("\n"); // 4 5 6 9 10return 0;
}
- 示例二:比较字符
int compareCharFunc(const void *arg1, const void *arg2){return (*(char*)arg1 - *(char*)arg2);
}int compareChar(void){char cha[] = {'B', 'D', 'A', 'W', 'Z', 'X', 'M', 'O'};int i;// Size of the arrayint size = sizeof(cha) / sizeof(cha[0]);printf("Original array elements:\n");for (i = 0; i < size; i++){printf("%c ", cha[i]);}printf("\n");// Use qsort to sortqsort(cha, size, sizeof(char), compareCharFunc);printf("Following is the sorted array: ");for (i = 0; i < size; ++i){printf("%c ", cha[i]); // A B D M O W X Z}return 0;
}
- 示例三:比较字符串
// 比较字符串
int compareStringFunc(const void *arg1, const void *arg2){return strcmp(*(const char **)arg1, *(const char **)arg2);
}int compareString(void){char *strings[] = {"Vivek", "Amanaaa","Aman", "Shriansh", "Tapas"};int i;// Size of the arrayint size = sizeof(strings) / sizeof(strings[0]);printf("Original array elements:\n");for (i = 0; i < size; i++){printf("%s ", strings[i]);}printf("\n");// Use qsort to sortqsort(strings, size, sizeof(char *), compareStringFunc);printf("Following is the sorted array: ");for (i = 0; i < size; ++i){printf("%s ", strings[i]); // Aman Amanaaa Shriansh Tapas Vivek}return 0;
}
参考
- 菜鸟教程
- tutorialspoint
- geeksforgeeks
- C语言刷题常用基础知识