1.strcpy()
在字符串拷贝函数中,它的函数编写不难,如下
char* Strcpy(char* dest, const char* src) {
assert(dest != NULL && src != NULL);
char* result = dest;
while (*src != '\0') {
*dest = *src;
src++;
dest++;
}
*dest = '\0';
return result;
}
但是,我们要注意的是, 目标内存的空间大小能否存储下源字符串的内容,在C语言中这一点,只能通过程序员来保证,所以往后再使用此类函数时候,一定要注意这一点.
2.strstr()函数
主要用来判断两个字符串是否为父子关系,也就是说str2字符串是否为Str1字符串的子串.我们自定义的函数里面使用了红黑指针用来标记子字符串首地址.
const char* Strstr(const char* str1, const char* str2) {
//避免违法内存
assert(str1 != NULL && str2 != NULL);
if (*str2 == '\0') {
//此时说明str2是一个空字符串
return NULL;
}
const char* black = str1;
while (*black != '\0') {
const char* red = black;
const char* sub = str2;
while((*red == *sub) && *red != '\0' && *sub != '\0' ) {
//三个结束条件
//1. *red *sub不一样
//2. red到头未找到
//3. sub到头找到
red++;
sub++;
}
if (*sub == '\0') {//if顺序不可调换
return black; //sub到头,找到子字符串
}
if (*red == '\0') { //red到头没找到子字符串
return NULL;
}
black++; //继续处理下次循环匹配
}
return NULL; //到头也没找到
}
3.strcat()函数 字符串拼接函数
char* Strcat(char* dest, const char* src) {
if (dest == NULL || src == NULL) {
return NULL;
}
// 1. 先找到 dest 的结束位置
int cur = 0;
while (dest[cur] != '\0') {
cur++;
}
// 循环结束之后, cur 下标位置就是 \0
// 2. 再把 src 往 dest 的结束位置进行拷贝
int i = 0;
while (src[i] != '\0') {
dest[cur + i] = src[i];
i++;
}
// 最后的设置 \0 千万不要遗漏
dest[cur + i] = '\0';
return dest;
}
4.字符串内个数 strlen()
int Strlen(const char* str) {
assert(str != NULL);
int size = 0;
while (*str != '\0') {
size++;
str++;
}
return size;
}
5.strcmp()两字符串按照字典序比较大小
int Strcmp(const char* str1, const char* str2) {
// 针对这个函数来说, 不太好用返回值来表示出错情况
assert(str1 != NULL && str2 != NULL);
// 依次比较两个字符串对应字符是否相等
while (*str1 != '\0' && *str2 != '\0') {
if (*str1 < *str2) {
return -1;
} else if (*str1 > *str2) {
return 1;
} else {
// 当前字符难分高下
// 继续再去比较下一个字符
str1++;
str2++;
}
}
// 看是哪个字符串先到达 \0 哪个字符串就更小
if (*str1 < *str2) {
return -1;
} else if (*str1 > *str2) {
return 1;
} else {
return 0;
}
}
6.内存拷贝memcpy()
void* Memcpy(void* dest, const void* src, size_t num) {
assert(dest != NULL && src != NULL);
void* ret = dest;
for (size_t i = 0; i < num; i++) {
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
以上的字符串函数和内存拷贝函数中,都要注意目标存储空间的大小能否容纳下源字符串或内容的大小.在C语言中这一点,只能通过程序员来保证,所以往后再使用此类函数时候,一定要注意这一点.
7.memmove()
在改良的条件下,多传入一个函数用于规避以上的内存访问越界问题中,memMove()函数能避免此类问题.
void* Memmove(void* dest, const void* src, size_t num) {
assert(dest != NULL && src != NULL);
// 先判定缓冲区内存是否重叠
char* cdest = (char*)dest;
char* csrc = (char*)src;
if (csrc < cdest && cdest < csrc + num) {
// 需要从后往前拷贝
char* pdest = cdest + num - 1; // 最后一个位置的字节
char* psrc = csrc + num - 1;
for (size_t i = 0; i < num; i++) {
*pdest = *psrc;
pdest--;
psrc--;
}
} else {
Memcpy(dest, src, num);
}
return dest;
}
此函数的功能在于,发现两个内存空间重叠时,会调换拷贝的方式为:从后往前拷贝;
如果不重叠,则按照memcpy()拷贝,