字符函数和字符串函数
strlen函数
size_t strlen (conse char * str);
注意:
1.字符串以 \0 作为结束标志,strlen函数返回的是在字符串中 \0 之前出现的字符个数(不包括\0)
2.函数的返回类型是size_t,是无符号的。
3.参数指向的字符串必须以 \0 结束。
对于第二点,以代码进行分析
int main()
{
char *p1 = "abc";
char *p2 = "abcde";
if (strlen(p1) - strlen(p2) > 0)
{
printf("A\n");
}
else
{
printf("B\n");
}
return 0;
}
输出结果是A。因为这个函数的返回类型是一个无符号整数,而在表达式计算中如果包含了一个或多个无符号整数的话那么算出来的结果也是无符号整数。
模拟实现strlen
三种方法
1.使用count临时变量
#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t my_strlen(const char * str)
{
assert(str);
int count = 0;
while (*str)
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "word";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
这里对str进行了解引用操作,如果指针是空指针,那程序会发生崩溃。所以在这里要用断言来对str是否为空指针进行判断。
2.不使用临时变量——递归
size_t my_strlen(const char * str)
{
assert(str);
if (*str)
{
return 1 + strlen(str + 1);
}
else
return 0;
}
int main()
{
char arr[] = "word";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
3.使用指针相减
指针-指针=中间元素的个数
size_t my_strlen(const char * str)
{
assert(str);
const char * start = str;
while (*str)
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "word";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
strcpy函数
char * my_strcpy(char * destination,const char * source);
1.源字符必须以\0结尾
2.拷贝的时候会把源字符的\0也拷过来
3.目标空间必须足够大,能容纳下源字符串
模拟实现strcpy
char * my_strcpy(char*dest, const char * src)
{
char *ret = dest;
assert(dest);
assert(src);
while (*src)
{
*dest = *src;
dest++;
src++;
}
*dest = *src;
return ret;
}
int main()
{
char * str = "ABCDE";
char arr[40] = "XXXXXXXXXXXXX";
my_strcpy(arr, str);
printf("%s\n", arr);
return 0;
}
代码还可以进行简化,最终简化代码如下↓
char * my_strcpy(char*dest, const char * src)
{
char *ret = dest;
assert(dest);
assert(src);
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char * str = "ABCDE";
char arr[40] = "XXXXXXXXXXXXX";
printf("%s\n", my_strcpy(arr, str));
return 0;
}
strcat函数
(字符串连接,字符串追加)
char * (char *destination,const char *source);
字符串不能自己追加自己。
模拟实现strcat
char * my_strcat(char * dest, const char *src)
{
char * ret = dest;
assert(dest);
assert(src);
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
printf("%s\n", my_strcat(arr1, "world"));
return 0;
}
输出结果hello world
strcmp函数
int strcmp(const char*str1,const char*str2)
字符串比较函数
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串小于第二个字符串,则返回小于0的数字
两个字符串相等,则返回0.
那么两个字符串是如何比较的呢?对两个字符串中相对应的字符的ASCII码值进行依次比较,如果两个字符串的第一个字符ASCII码值相等,那就继续比第二个大小。如果不相等,则就可以判断两个字符串的大小。
模拟实现strcmp
int my_strcmp(char* s1, char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
*s1++;
*s2++;
}
if (*s1 != *s2)
return *s1 - *s2;
}
int main()
{
char arr1[] = "abcd";
char arr2[] = "abfd";
int ret = my_strcmp(arr1, arr2);
printf("%d\n", ret);
return 0;
}
输出结果为-3,小于0,所以arr1<arr2。
strstr函数
char * strstr(const char *,const char *);
模拟实现strstr
char * my_strstr(const char * s1, const char * s2)
{
const char * cp = s1;
while (*cp)
{
s1 = cp;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
cp++;
if (*s2 == '\0')
{
return (char *)cp;
}
}
return NULL;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "bcd";
char * ret = my_strstr(arr1, arr2);
printf("%s\n", ret);
return 0;
}
memcpy函数
有了strcpy函数为什么还要用memcpy呢?
strcpy遇到\0就会停下来,所以当遇到int arr[]={1,2,3,4,5,}时(存储方式是01 00 00 00 02 00 00 00,01后面00就会让strcpy停下来)strcpy就不能将其拷贝。
void * memcpy(void * destination,const void * source,size_t num);
1.函数memcpy从source的位置开始向后复制num个字节的数据到destnation的内存位置
2.这个函数遇到 ‘\0’ 的时候不会停下来
3.如果source和destnation有任何的重叠,复制的结果都是未定义的
void * my_memcpy(void * dest, const void * src, size_t count)
{
assert(dest);
assert(src);
void * ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[20] = { 0 };
my_memcpy(arr2, arr1,sizeof(arr1));
return 0;
}
memmove函数
1.与memcpy函数的区别就是memmove函数处理的源内存块和目标内存是可以重叠的。
2.如果源空间和目标空间出现重叠,就得用memmove函数处理。
void * memmove(void * destnation,const void * source,size_t num);
memmove是分情况进行实现的(为了防止出现覆盖情况)
当dest>src,dest<src+num:从后往前copy
当dest>src+num:从前往后或者从后往前都可以
当dest<src:从前往后copy
模拟实现memmove
(对数组int arr1[ ]={1,2,3,4,5,6,7,8,9,10},把1 2 3 4 cpoy到3 4 5 6)
void * my_memmove(void * dest, const void * src, size_t num)
{
assert(dest);
assert(src);
void * ret = dest;
if (dest < src)
{
while (num--)
{
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
}
}
else
{
while (num--)
{
*((char *)dest + num) = *((char *)src + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr1 + 2, arr1, 16);
return 0;
}