目录
一、strlen函数
#include <stdio.h> int main() { const char*str1 = "abcdef"; const char*str2 = "bbb"; if(strlen(str2)-strlen(str1)>0) { printf("str2>str1\n"); } else { printf("srt1>str2\n"); } return 0; }
运行结果为str2>str1
原因:strlen返回值是无符号整形,3-6=-3是一个负数,在内存中以补码的形式表示,被当做一个无符号整形,所以补码就是原码,这是一个很大的大于0的数。
二、C语言模拟实现strlen函数的3种方法
1.计数器
//1.计数器 #include <stdio.h> #include <assert.h> int my_strlen(char* p) { assert(*p != NULL);//为了程序的健壮性 int count = 0; while (*p != '\0') { count++; p++; } return count; } int main() { char arr[] = "abcdef"; int num = my_strlen(arr); printf("%d ", num); return 0; }
2.递归 不能创建临时变量的写法
#include <stdio.h> int my_strlen(char* p) { if (*p == '\0') { return 0; } else return 1 + my_strlen(p + 1); } int main() { char arr[] = "abcdef"; int num = my_strlen(arr); printf("%d ", num); return 0; }
3.指针-指针
//指针-指针的方式 int my_strlen(char *s) { char *p = s;//s表示指针变量 while(*p != ‘\0’ ) p++; return p-s; }
使用的要求必须是2个指针指向同一块地址空间。
三、str系列函数
strcpy函数
char* strcpy(char * destination, const char * source );
tips:
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。 学会模拟实现。
int main()
{
char arr[20] = { 0 };
arr = "hello"; //err,因为arr是数组名,是地址,表示的是常量,是数字,你怎么能把
//"hello"赋值给它呢
printf("%s\n", arr);
}所以要这么写
int main() { char arr[20] = { 0 }; char* p = "hello"; strcpy(arr, p);//string copy printf("%s\n", arr); }
还可以这么写
int main() { char arr[20] = { 0 }; char* p = "hello"; strcpy(arr, p);//string copy printf("%s\n", arr); }
这里注意,arr[20]满足了目标空间足够大,能够放得下,源字符串必须以 '\0' 结束,而且数组目标空间可变,要是这里换成char *q="$$$$$$$$$$$$",则根本strcpy复制不了,因为目标空间不可变。
在举一个例子:
char *p="ASDFG",这里p的内容能改么?
答:不能,p指向的是常量字符串,你想让他改,不可能的,这辈子都不可能的。
strcat函数
char * strcat ( char * destination, const char * source );
源字符串必须以 '\0' 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
字符串不能自己给自己追加
理由:[a s d f \0]
[a s d f a s d f ....]
见到\0就追加原字符串内容,最后的结果是源字符串\0丢失了。一个字符数组只有一个空间,要在一个空间进行自己的字符串追加,找到’\0’后,将’a’赋给’\0’,此字符串就没有了字符串结束的标志,代码进入死循环。
strcat函数模拟实现
char *my_strcat(char *dest, const char*src) { char *ret = dest; assert(dest != NULL); assert(src != NULL); while(*dest) { dest++; } while((*dest++ = *src++)) { ; } return ret; }
char *ret = dest;这句话能去掉吗
不能,去掉后最后结果返不回来,需要有一个指针指向dest
strcmp模拟实现
int my_strcmp(const char* src, const char* dst)
{
int ret = 0;
assert(src != NULL);
assert(dst != NULL);
while (!(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
++src, ++dst;
if (ret < 0)
ret = -1;
else if (ret > 0)
ret = 1;
return(ret);
}
什么时候能够跳出循环?
当dst所指向的内容=\0或者src和dst目标内容dst不等于0(即不相等)时。
1.BF算法,暴力(Brute Force)算法
char* my_strstr(char* str1, char* str2){ assert(str1 && str2); int slen = strlen(str1); int sublen = strlen(str2); int i = 0; int j = 0; int count = 0; while(i < slen){ while(str1[i] == str2[j] && j < sublen){ ++i; ++j; } if(j >= sublen){ return str1 + i - j; } ++count; i = count; j = 0; } return NULL; }
2.KMP算法
#include<stdio.h> #include<string.h> #include<assert.h> #include<stdlib.h> void get_next(int* next, char* sub){ int len = strlen(sub); next[0] = -1; next[1] = 0; int i = 2; int k = 0; while(i < len){ if(k == -1 || sub[i-1] == sub[k]){ next[i] = ++k; ++i; }else{ k = next[k]; } } } char* my_strstr(char *str1, char * str2){ assert(str1 && str2); int slen = strlen(str1); int sublen = strlen(str2); int* next = (int*)malloc(sizeof(int)*sublen); assert(next); get_next(next,str2); int i = 0; int j = 0; while(i < slen && j < sublen){ if(j == -1 || str1[i] == str2[j]){ ++i; ++j; }else{ j = next[j]; } } if(i >= sublen){ return str1 + i - j; }else{ return NULL; } }