目录
strstr
char * strstr ( const char *str1, const char * str2);
- 在主串 str1 中,寻找与模式串 str2 相匹配的子串,返回第一个子串的首元素地址
- 未找到则返回空指针
strstr模拟实现
- 方法一:BF算法(暴力算法)
char* my_strstr(const char* str1, const char* str2) {
assert(str1 && str2);
const char* s1 = str1;
const char* s2 = str2;
int lenS1 = strlen(s1);
int lenS2 = strlen(s2);
if (lenS1 == 0 || lenS2 == 0) {
return -1;
}
char* cur = str1; // cur暂存子串开始的位置
while (*cur) {
s1 = cur; // s1接收暂存的子串
s2 = str2; // s2回到模式串起始位置
// 不相等或者某一项遍历完成则跳出循环
while (*s1 == *s2) {
s1++;
s2++;
}
// 跳出循环后,如果s2遍历结束,说明找到了匹配的子串
if (*s2 == '\0') {
return cur;
}
cur++; // 从主串的下一个字符开始比较
}
return NULL;
}
- 方法二:KMP算法
KMP算法详解请看——链接: KMP算法——(手把手算next数组)
void GetNext(char* sub, int* next, int lenSub) {
next[0] = -1;
next[1] = 0;
int i = 2; // 当前下标
int k = 0; // 前一项的k,即前一项回退的下标
// 当前 i=2 的前一项next数组值为0
while(i < lenSub) {
if (k == -1
|| sub[i - 1] == sub[k]) { // k == -1 sub[k]会越界,但是也得进入
next[i] = k+1;
i++;
k++;
}
else {
k = next[k];
}
}
}
char* my_strstr_KMP(const char* str1, const char* str2) {
assert(str1 && str2);
// str:代表主串 sub:代表子串
char* str = str1;
char* sub = str2;
int lenStr = strlen(str);
int lenSub = strlen(sub);
if (lenStr == 0 || lenSub == 0) {
return NULL;
}
int* next = (int*)malloc(sizeof(int) * lenSub);
assert(next);
GetNext(sub, next, lenSub);
int i = 0; // 遍历主串
int j = 0; // 遍历子串
while (i < lenStr && j < lenSub) {
if (j == -1 || str[i] == sub[j]) { // j == -1
i++; j++;
}
else {
j = next[j];
}
}
// 定位子串开始地址
if (j >= lenSub) {
char* ret = str1;
int lend = i - j;
while (lend) {
ret++;
lend--;
}
return ret;
}
return NULL;
}
strtof
char * strtok ( char * str, const char * sep );
- sep 中定义了用作分隔符的字符集合
- str 是一个包含了0个或者多个由 sep 字符串中一个或者多个分隔符分割的标记的字符串
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针
- strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改,使用方法如下:
int main() {
char arr[] = "sdadwqd@163.com";
const char* sep = "@.";
char tmp[50] = { 0 };
strcpy(tmp, arr);
printf("%s\n", strtok(tmp, sep));
printf("%s\n", strtok(NULL, sep));
}
运行结果如下:
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串
中的位置。 - strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标
记。 - 如果字符串中不存在更多的标记,则返回 NULL 指针。
另一种循环使用方法如下:
int main() {
char arr[] = "sdadwqd@163.com";
const char* sep = "@.";
char tmp[50] = { 0 };
strcpy(tmp, arr);
char* str = NULL;
for (str = strtok(tmp, sep); str != NULL; str = strtok(NULL, sep)) {
printf("%s\n", str);
}
return 0;
}
运行结果如下:
strerror
#include <errno.h>
char * strerror ( int errnum );
- 返回错误码,所对应的错误信息
具体使用举例如下:
int main() {
int* p = (int*)malloc(INT_MAX);
if (p == NULL) {
printf("%s\n", strerror(errno));
return 1;
}
return 0;
}
- malloc开辟空间失败,返回空指针,使用 strerror 打印错误信息
运行结果如下:
memcpy
void * memcpy ( void * dest, const void * src, size_t count);
- count单位是字节
- 从 src 的位置开始向后复制 count个字节的数据到dest 的内存位置
- 这个函数在遇到 ‘\0’ 的时候并不会停下来
- 如果 src 和 dest 有任何的重叠,复制的结果都是未定义的;要实现重叠拷贝,需要使用 memmove(但是在vs编译器上memcpy和memmove一致)
memcpy模拟实现
void* my_memcpy(void* dest, const void* src, size_t count) {
assert(dest && src);
void* ret = dest;
while (count--) {
// 因为count单位为字节,所以将指针强制类型转换为字符指针,按字节进行处理
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
memmove
void * memmove ( void * dest, const void * src, size_t count );
- 和 memcpy 的差别就是 memmove 函数处理的源内存块和目标内存块是可以重叠的
memmove模拟实现
void* my_memmove(void* dest, const void* src, size_t count) {
assert(dest && src);
void* ret = dest;
if (dest < src) {
// 前—>后
while (count--) {
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else {
// 后—>前
while (count--) {
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
- 与 strcmp 类似,不同在于是按字节进行比较
memcmp模拟实现
void* my_memcmp(const void* ptr1, const void* ptr2, size_t count){
assert(ptr1 && ptr2);
const char* p1 = (const char*)ptr1;
const char* p2 = (const char*)ptr2;
int ret = 0;
while (count--){
if ((ret = *p1 - *p2) != 0)
break;
p1++;
p2++;
}
return ret;
}
memset
void* memset( void * dest, int c, size_t count);
- 以字节为单位来初始化内存单元
memset模拟实现
void* my_memset( void * dest, int c, size_t count){
assert(dest != NULL);
char* pdest = (char*)dest;
while (count--)
{
*pdest++ = c;
}
return dest;
}