进一步认识字符串
实现memmove
用C语言实现函数void * memmove(void *dst, const void *src, size_t n)
。memmove函数的功能是复制src所指的内存内容前n个字节到dest所指的地址上
这个函数的参数与返回值的类型都是void*
,在实现的时候需要把void*
转换成可操作的数据类型来处理
主要特别考虑的是内存重叠问题,处理内存重叠的主要思路如下:
- 当源内存的首地址大于目标内存的首地址时,从源内存的首地址开始复制
- 当源内存的首地址小于目标内存的首地址时,从源内存的首地址加待复制字节长度的地址开始逆序复制
实现代码如下:
void * mymemmove(void *dst, const void *src, size_t num)
{
if (dst == NULL || src == NULL)
{
return NULL;
}
char *pdst = (char *)(dst);
const char *psrc = (char *)(src);
//内存重叠的情况
if (pdst > psrc && pdst < psrc + num)
{
for (size_t i = num - 1; i != -1; i--)
{
pdst[i] = psrc[i];
}
}
else
{
for (size_t i = 0; i < num; i++)
{
pdst[i] = psrc[i];
}
}
return dst;
}
总结5个需要注意的地方:
- 对异常进行判断,判断src与dst是否为空指针
- src指针要用const修饰,以避免无意中修改src的内容
- 在实现的时候,需要把
void*
转换成能进行操作的数据类型,如char*
- 函数需要返回值,这样这样支持链式表达
- 需要特别考虑指针重叠的情况
实现memcpy函数
memcpy函数的功能是从源src所指的内存地址的起始位置开始复制n个字节到目标dest所指的内存的起始位置中。函数原型为
void *memcpy(void *dest, const void *src, size_t n)
memcpy与memmove的功能类似。只不过memmove函数在有内存重叠的情况下也能保证数据复制的正确性;而memcpy在内存不重叠的情况下能保证数据复制的正确性,对于内存重叠的情况,不能保证数据复制的正确性,具体情况根据不同类库的实现有关
实现strcpy()函数
strcpy的原型为extern char *strcpy(char *dest, const char *src);
,包含在头文件string.h
中,它返回指向dest的指针,其功能是把src所指由'\0'
结束的字符串复制到dest所指的数组中。值得注意的是,dest必须有足够的空间容纳src的字符串,src字符串尾的字符串结束标识符'\0'
也会被复制过去
另外还需要考虑内存重叠问题,于是可以直接用memmove函数实现
char * strcpy(char *dest, char *src)
{
assert(dest != NULL && src != NULL);
char *returnValue = dest;
memmove(dest, src, strlen(src) + 1);
return returnValue;
}
size_t strlen(const char* str)
{
assert(str != NULL);
size_t length = 0;
while ((*str++)!='\0')
length++;
return length;
}
strstr函数的作用是什么
函数原型:extern char *strstr(char *str1, char *str2);
功能:strstr(str1, str2)函数用于判断字符串str2是否是str1的子串。如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL
实现atoi(字符串转换成整型数)
int myatoi(char *str)
{
if (str == NULL)
{
printf("Invalid Input");
return -1;
}
while (*str == ' ') //去掉字符串开始的空格
{
str++;
}
int nSign = (*str == '-') ? -1 : 1; //确定符号位
if (*str == '+' || *str =='-')
{
str++;
}
int nResult = 0;
while (*str >= '0' && *str <= '9')
{
nResult = nResult * 10 + (*str - '0');
str++;
}
while (*str == ' ') //去掉字符串结束的空格
{
str++;
}
if (*str != '\0')
{
printf("Invalid Input");
return -1;
}
return nResult * nSign;
}
实现itoa(整型数转换成字符串)
由于int可以表示数的范围为-2147483648~2147483647,因此吧int转换为字符串后,字符串最大的长度为11,因此最多需要的空间为12
char *myitoa(int num, char str, int radix)
{
char ptr = str;
int temp;
int sign = num, i == 0, j = 0;
if (sign < 0)
{
num = -num;
}
while (num)
{
*ptr++ = num % radix + '0';
num /= radix;
if (num < radix)
{
*ptr++ = num + '0';
break;
}
}
if (sign < 0)
{
*ptr++ = '-';
}
*ptr = '\0';
j = ptr - str - 1;
for (i = 0; i < j; i++)
{
int temp = str[i];
str[i] = str[j];
str[j--] = temp;
}
return str;
}