求字符串的长度:strlen
size_t strlen(const char *str);
字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
参数指向的字符串必须要以 ‘\0’ 结束。
注意函数的返回值为size_t,是无符号的
#include <stdio.h>
int My_strlen(const char *ch) //加const是为了不要让其他的条件改变ch的值
{
int count = 0; //定义一个计数器count
while((*ch++)!='\0') //只要ch数组里面的字符串不是\0则计数器就加1
{
count++;
}
return count; //将计数器的值返回
}
int main()
{
char ch[]="abcdef";
int len = My_strlen(ch);
printf("%d\n",len);
return 0;
}
长度不受限制的字符串函数
strcpy
char *strcpy(char * destination, const char * source);
源字符串必须以 '\0' 结束。
会将源字符串中的 '\0' 拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可变。
void My_strcpy(char *dest,const char *src) //加const的目的是为了保证src所指向的字符串不被外界因素改变
{
while((*dest++=*src++)&&*src!='\0') //将src里的字符复制给dest
;
*dest++ = '\0'; //上面的复制并没有将\0复制给dest,所以这里要加上
}
int main()
{
char arr[]="abcdef";
char aim[7];
My_strcpy(aim,arr);
printf("%s\n",aim);
return 0;
}
strcat(字符串的追加)
char * strcat(char destnation, const char source);
源字符串必须以 ‘\0’ 结束。
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
char* my_strcat(char* dest, char* src)
{
char *cp = dest;
assert(src && dest);
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return cp;
}
int main()
{
char str[32] = "abcd";
char buf[32] = "efgh";
printf("%s\n", my_strcat(str, buf));
system("pause");
return 0;
}
strcmp(字符串的比较)
int strcmp (const char* str1, char * str2);
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* arr1,const char* arr2)
{
int ret=0;
assert(arr1);
assert(arr2);
while( !(ret = *(unsigned char*) arr1 - *(unsigned char* ) arr2 ) // 整形提升
&& *arr1) //两个条件同时满足才执行循环内容
{
arr2++;
arr1++;
}
if(ret<0)
return -1;
else if(ret>0)
return 1;
else
{
; //do nothing
}
return 0;
}
int main()
{
char arr1[]="123abcd";
char arr2[]="123Abcd";
char arr3[]="123Abcd";
printf("%d\n",my_strcmp(arr1,arr2));
printf("%d\n",my_strcmp(arr2,arr3));
printf("%d\n",my_strcmp(arr3,arr1));
return 0;
}
strstr(判断是否是子串)
char strstr(const char ,const char*)
char* my_strstr(const char*str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
//下面这个if语句判断str2是不是空的,
//如果是空则直接返回str1
if (*str2 == '\0')
{
return (char*)str1;
}
while (*str1 != '\0')//当str1没到‘\0’时,执行下面,否则返回NULL
{
const char* p1 = str1;//创建新指针指向str1
const char* p2 = str2;//同上
while (*p2 != '\0')
{
if (*p1 != *p2)
{
break;
}
else
{
p1++;
p2++;
}
}
if ('\0' == *p2)
{
return (char*)str1;
}
++str1;
}
return NULL;
}
int main()
{
char *str1 = "hello world";
char *str2 = "llo";
printf("%s", strstr(str1, str2));
system("pause");
return 0;
}
memcpy
void *memcpy(void * destnation ,const void * source,size_t num);
函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
这个函数在遇到 ‘\0’ 的时候并不会停下来。
如果source和destination有任何的重叠,复制的结果都是未定义的
void* my_memcpy(void* dest, const void* src, size_t n)
{
assert(dest);
assert(src);
char* pdest = (char*)dest;
const char* psrc = (const char*)src;
while (n--)
{
*pdest++ = *psrc++;
}
return dest;
}
memove
int memcmp(const void * ptr1,
const void *ptr2,
size_t num)
和memcpy的差别就是memove函数处理的源内存块和目标内存块是可以重叠的
如果源空间和目标空间出现重叠,就得使用memove函数处理
void *MyMemmove(void * dest, const void * src, size_t num)
//和memcpy最大的不同就是,它是内存移动,反向拷贝,不是从头开始
{
void *ret = dest;
char *str1 = (char*)dest;
char *str2 = (char*)src;
if(str1>str2)
//只有当前面的位置比后面的位置高,才会反向拷贝,因为会有覆盖现象
{
while(num--)
{
*(str1+num) = *(str2+num);//反向赋值
}
}
else
{
while(num--)
{
*str1++ = *str2++;
}
}
return ret;
}
memcmp
int memcmp(const void * ptr1,
const void * ptr2,
size_t num);
比较从ptr1和ptr2指针开始的num个字节
int my_memcmp2(const void *p1, const void *p2, size_t count)//方法2
{
assert(p1);
assert(p2);
int ret = 0;
char *dest = (char *)p1;
char *src = (char*)p2;
while (count && (!(ret = (*dest - *src))))
{
dest++;
src++;
count--;
}
if (ret > 0)
{
return 1;
}
else if (ret < 0)
{
return -1;
}
return 0;
}
int main()
{
int arr1[] = {1,2,3,4,5,6};
int arr2[] = {1,2,3,1000000,5,6};//清楚内存是怎样放置的
int ret = my_memcmp2(arr1, arr2, 16);
printf("%d", ret);
system("pause");
return 0;
}