- strlen 函数的实现
int my_strlen(char* dst) {
assert(dst);
char* ret = dst;
int count = 0;
while (*ret!='\0') {
++ret;
++count;
}
return count;
}
- strcat 函数的实现
har* my_strcat(char* dst, const char* src) {
assert(dst && src);
char* ret = dst; // 因为后边 dst需要++,所以用ret保存原来的位置
while (*dst != '\0') { //先找到 dst 上'\0' 的位置
++dst;
}
while (*dst++ = *src++); //当 dst 到 '\0'了,再将 src 传给 dst
return ret;
}
和strcpy 不同的是 strcpy是拷贝,strcat是追加拷贝。
- strcmp 函数的实现
int my_strcmp(const char* str1,const char* str2) {
assert(str1 && str2);
unsigned char* s1 = (unsigned char*)str1;
unsigned char* s2 = (unsigned char*)str2;
while (*s1 && *s2) {
if (*s1 > *s2) {
return 1;
}
else if (*s1 < *s2) {
return -1;
}
else {
++s1;
++s2;
}
}
if (*s1 == '\0'&&*s2 == '\0') {
return 0;
}
else if (*s1 == '\0') {
return -1;
}
else {
return 1;
}
}
strcmp 函数居然是根据字符串中字符的 ASCII 码大小来比较字符串大小的,我有一点不解,假如有两个字符串 str1 = “abbb” 和 str1 = “baaa”,用 strcmp 函数的话,结果是 str2 大于 str1,仅仅是因为 str2 的第一个字符 b 的 ASCII 码大于 str1 的 a。我的想法是应该比较总的 ASCII 码的大小。(仅仅是我自己的臆想,还是按照人家的来吧!)
- strstr 函数的实现
判断一个字符串是不是另一个字符串的子串,如果是,则该函数返回 str2 在 str1 中首次出现的地址,否则,返回NULL。
char* my_strstr(const char* src, const char* sub) {
assert(src && sub);
const char* srci = src;
const char* subi = sub;
while (*srci != '\0') {
while (*srci == *subi && *subi != '\0') {
++srci;
++subi;
}
if (*subi == '\0') {
return src;
}
else {
subi = sub;
++src;
srci = src;
}
}
}
- memcpy 函数的实现
void* my_memcpy(void* dst, const void* src, size_t num) {
assert(dst && src);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i]; // 等价于 *(str_src + i)
}
return dst;
}
memcpy函数和strcpy函数的一个区别在于,memcpy可以拷贝任意类型的数据,而strcpy函数只能拷贝字符串
-
memmove 函数的实现
memmove 函数有两种实现的方法。
如图要将红色部分的数据拷贝到黑色部分,第一种情况是内存的前重叠,和不重叠,直接从 src 的前往 src 的后拷贝给 dst,不会影响结果。但是如果是内存的后重叠,如下图:
如果还是按照从前往后进行拷贝,把 src 的第一个数据拷给 dst 的第一个数据时,就已经改变了 src 后边的数据,因为 dst 第一个数据所在位置刚好重叠与 src 后边的数据,这样拷贝,已经改变了还没有拷贝给 dst 的数据,后边拷贝的数据并不是我们最初想要的。所以这种内存后重叠,我们就要从后往前进行拷贝,也就是说,先把 src 的最后一个数据拷贝给 dst 的最后一个数据,然后把 src 的倒数第二个数据拷贝给 dst 的倒数第二个数据,以此类推。这样做就不会改变还没有拷贝给 dst 的 src 数据。
以下有两种拷贝方式,第一种是:给前重叠或者不重叠从前往后拷贝,给后重叠或者不重叠从后往前拷贝(从前往后或者从后往前拷贝都不会影响到内存不重叠的拷贝)。 第二种是:给内存前重叠或者不重叠的从前往后拷贝,给内存后重叠的从后往前拷贝。第一种
void* my_memmove(void* dst, const void* src, size_t num) {
assert(src && dst);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
if (str_dst < str_src) { //前重叠或者不重叠,从前往后拷贝
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i];
}
}
else {//后重叠或者是不重叠,从后往前拷贝
for (int i = num-1 ; i >= 0; --i) {
str_dst[i] = str_src[i];
}
}
return dst;
}
**第二种**
void* my_memmove(void* dst, const void* src, size_t num) {
assert(src && dst);
char* str_dst = (char*)dst;
char* str_src = (char*)src;
if (str_src < str_dst && str_dst<str_src +num) { //后重叠 从后往前拷贝
for (int i = num - 1; i >= 0; --i) {
str_dst[i] = str_src[i];
}
}
else { //前重叠或者不重叠,从前往后拷贝
for (size_t i = 0; i < num; ++i) {
str_dst[i] = str_src[i];
}
}
return dst;
}
值得一提的是,字符串数组可以用这种方式初始化(char str[] = “abcdefg”),但是不可以用这种方式赋值,这里就可以用到字符串函数 strcpy memcpy memmove