1.strlen求字符串长度
size_t strlen ( const char * str );
(1)字符串将’\0’作为结束标志,strlen函数返回的是在字符串中’\0’前面出现的字符个数(不包含’\0’)
(2)参数指向的字符串必须要以’\0’结束
(3)注意函数的返回值为size_t,是无符号的
strlen函数的模拟实现:
#include<stdio.h>
#include<assert.h>
int my_strlen(const char*str)
{
assert(str != NULL);
int count = 0;//计数器
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char string[] = "abcdef";//应将字符串放入一个字符型数组中
int ret = 0;
ret = my_strlen(string);
printf("字符串长度为:%d\n",ret);
system("pause");
return 0;
}
2.strcpy拷贝
char * strcpy ( char * destination, const char * source );
(1)源字符串必须以’\0’结束。
(2)会将原字符串中的’\0’拷贝到目标空间。
(3)目标必须足够大,以确保能存放源字符串。
(4)目标空间必须可变。
strcpy函数的模拟实现:
#include<stdio.h>
#include<assert.h>
char *my_strcpy(char *dst, const char *src)
{
char *ret = dst;//将目标空间的起始地址,保存在临时变量ret中,方便函数或系统进行链式调用。
assert(dst != NULL);
assert(src != NULL);
while (*dst = *src)//'='是为了保证在进行拷贝的时候,也同时把\0拷贝到目标空间,完成拷贝。
{
dst++;
src++;
}
return ret;
}
int main()
{
char arr1[7] = "abcdef";
char arr2[20] = { 0 };
printf("%s\n", my_strcpy(arr2, arr1));
system("pause");
return 0;
}
3.strcat拼接(拼接也是拷贝)
char * strcat ( char * destination, const char * source );
(1)源字符串必须以’\0’结束。
(2)目标空间必须足够大,能容纳下源字符串的内容。(需要dst预留足够的空间,容纳拷贝内容)
(3)目标空间必须可以修改。
stract函数的模拟实现:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char *dst, const char *src)
{
assert(dst != NULL);
assert(src != NULL);
char* ret = dst;
while (*dst)//*dst即*dst !='\0'
{
dst++;
}
//dst -> \0
while (*dst = *src)
{
dst++;
src++;
}
return ret;
}
int main()
{
const char* src = "abcd1234";
char dst[16] = "XYZ";
my_strcat(dst, src);
printf("dst: %s\n", dst);
system("pause");
return 0;
}
4.strcmp字符串大小比较
int strcmp ( const char * str1, const char * str2 );
(1)比较规则,从左向右,只要特定字符不相等,哪个字符大,所在的字符串就大和长短无关(ASCII码值比较)
(2)str1>str2,返回大于0的数字;
(3)str1=str2,返回0;
(4)str1<str2,返回小于0的数字。
strcmp函数的模拟实现:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char *s1, const char *s2)
{
assert(s1 != NULL);
assert(s2 != NULL);
int ret = 0;
//类型强转
const unsigned char* _s1 = (const unsigned char*)s1;
const unsigned char* _s2 = (const unsigned char*)s2;
//!(ret == (*_s1 - *_s2)):满足,说明*_s1 == *_s2
while (!(ret = (*_s1 - *_s2)) && *_s1)//*_s1即*_s1 !='\0'
{
_s1++;
_s2++;
}
if (ret < 0)
{
ret = -1;
}
else if (ret > 0)
{
ret = 1;
}
else
{
ret = 0;
}
return ret;
}
int main()
{
const char* _s1 = "abcd1236";
const char* _s2 = "abcd1234";
int ret = my_strcmp(_s1, _s2);
printf("%d\n", ret);
system("pause");
return 0;
}
5.strstr查找功能
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
strstr函数的模拟实现:
#include<stdio.h>
#include<assert.h>
//target: 目标字符串,被查找的
//sub: 查找子串,需要查找的
//return NULL, not found else found it!
const char* my_strstr(const char *target, const char *sub)
{
assert(target != NULL);
assert(sub != NULL);
//->target
const char* start = target;
const char* move = NULL;
//->sub
const char* sub_start = NULL;
//整体移动的
while (*start)
{
sub_start = sub;
move = start;
//局部比较的
while (*start && *move && *move == *sub_start)
{
move++;
sub_start++;
}
//
if (*sub_start == '\0')
{
return start;
}
//not found
start++;
}
return NULL;
}
int main()
{
const char* target = "abc123abcd4567123xyz";
const char* sub_str = "xyz";
printf("%s\n", my_strstr(target, sub_str));
system("pause");
return 0;
}
6.memcpy复制功能
void * memcpy ( void * destination, const void * source, size_t num );
(1)函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
(2)这个函数在遇到’\0’的时候并不会停下来。
(3)如果source和destination有任何的重叠,复制的结果都是未定义的。
memcpy函数的模拟实现:
#include<stdio.h>
#include<assert.h>
void* my_memcpy(void *dst, const void *src, size_t num)
{
assert(dst != NULL);
assert(src != NULL);
if (num == 0)
{ //TODO
return dst;
}
unsigned char* _dst = (unsigned char*)dst;
unsigned char* _src = (unsigned char*)src;
while (num)
{
*_dst = *_src;
_dst++;
_src++;
num--;
}
return dst;
}
int main()
{
char src[32] = "abcdefg";
char dst[32] = { 0 };
my_memcpy(src, src + 1, strlen(src));
my_memcpy(src+ 1, src , strlen(src) + 1);//出现内存重叠问题
printf("%s\n", src);
system("pause");
return 0;
}
7.memmove复制功能
void * memmove ( void * destination, const void * source, size_t num );
(1)和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的(新版本编译器两个函数都可以)。
memmove函数模拟实现:
#include<stdio.h>
#include<assert.h>
void *my_memmove(void *dst, const void *src, int num)
{
assert(dst != NULL);
assert(src != NULL);
if (num <= 0) {
return NULL;
}
//字节单位
unsigned char* _dst = (unsigned char*)dst;
unsigned char* _src = (unsigned char*)src;
if (_dst > _src && _dst < _src + num) {
//right->left
_src = _src + num - 1;
_dst = _dst + num - 1;
while (num) {
*_dst = *_src;
_dst--;
_src--;
num--;
}
}
else {
while (num) {
*_dst = *_src;
_dst++;
_src++;
num--;
}
}
return dst;
}
int main()
{
char src[32] = "abcdefg";
char dst[32] = { 0 };
my_memmove(src, src + 1, strlen(src));
printf("%s\n", src);
system("pause");
return 0;
}