注意 : 字符串函数和内存处理函数都具有破坏性!
1.strcpy 字符串复制函数
char * strcpy ( char * destination, const char * source);
这个函数会将两个字符串按照从前端对齐,然后利用指针的自增和赋值来将 source指向的字节的内容赋值给destination的对应位置上,直到source的指针指向了\0.
模拟实现:
char * my_strcpy(char* des,char * sou)
{
char* p = des;
while (*sou)
*des++ = *sou++;
return p;
}
char* pengge_strcpy(char* des, char* sou)
{
char* p = des;
while (*des++ = *sou++);
return p;
}
如果destination 指向的字符串没有\0,程序cpy正常运行;
如果source指向的字符串没有\0,source的内容的按字节赋值将无法找到终点,字符串的长度无法确定,此时就要越界访问,还可能崩溃。
注意cpy前后dest字符串能不能放得下。
2.strncpy 前 num 位的字符串的总结
char * strncpy ( char * destination, const char * source,size_t num)
这个函数会将source的前n个字符赋给前num位destination指向的字符,并且不会主动赋值\0.
注意cpy前后dest字符串能不能放得下。
如果 num 大于了source长度,就会赋值 '\0'直到赋满了 n 个字符为止。
如果num 大于了destination的长度,程序就要崩溃。
3.strcat 字符串追加函数
char * strcat ( char * destination, char * source);
这个函数会将source指向的字符串追加到destination字符串之后。
先在destination中检索到\0, 然后然后进行对应位置上的赋值,其中destination原有的\0会被覆盖。最后整个source会被赋到destination的后方,包括source中的\0。
注意一下source函数有没有\0即可。
模拟实现:
char * my_strcat(char* des, const char* sou)
{
char* p = des;
while (*des)
des++;
while (*des++ = *sou++);
return p;
}
4.strncat 前n 位字符串追加函数
char * strncat ( char * destination, const char * source,size_t num);
在 destination指向的字符之后 追加 num 位来自source指向的字符串的字符。
不论num是多少,这个函数在追加完之后都会给一个\0,不论destinatin字符串有多长。
5.strcmp 字符串比较函数 与长度无关,与每一位ASCII码有关
int strcmp( const char * destination,const char * source,size_t num);
将destination和source指向的字符串左端对齐,逐字符比较这一位上的ASCII码.
如果对于某一位, *dest > *sour,返回正数; * dest < * sour ,返回负数;
如果对于每一位均有 * dest == * source,就返回0.
模拟实现:
#include <stdio.h>
#include < string.h>
int mystrcmp(const char* p1, const char* p2)
{
while (*p1 == *p2)
{
if (*p1 == 0)
return 0;
else
{
p1++;
p2++;
}
}
if (*p1 > *p2)
return 1;
else
return -1;
}
6.strncmp 前num位字符串比较函数
int strncmp(char * destination, char * source,size_t num);
可以将source的前num位和destinaation的前n位进行比较,其余的和strcmp一致。
7.strlen 获得字符串的长度
size_t strlen ( const char *str);
这个函数会从传入的地址为字符串的起始地址,然后向后寻找\0来截止,返回第一个元素的地址到第一个\0的地址的差的绝对值,并且不算上\0本身。
如果找不到\0,strlen会一直在内存中向高地址寻找\0,此时就有可能发生越界访问。
另外:size_t 是无符号整形, size_t情况下,负数会被编译器看成是很大的正数。
strlen可以用这样的方式实现:
size_t my_strlen(char* arr)
{
size_t cnt = 0;
int i = 0;
assert(arr != NULL);
while (arr[i++])
cnt++;
return cnt;
}
size_t mystrlen(char* p1)
{
assert(p1 != NULL);
char* start = p1;
while (*p1)
p1++;
return p1 - start;
}
size_t mystrlen_no(char* p1)
{
if (*p1 == 0)
return 0;
else
return 1 + mystrlen_no(p1 + 1);
}
8.strstr 字符串搜查函数
char * strstr( const char * str1,const char * str2)
返回整个字符串在str1中出现的首元素地址。如果没找到返回NULL,如果有多个,就返回第一次在str1中出现的首元素地址。
模拟实现:
char* mystrstr(char* p1, char* p2) // 回溯
{
char* cur = p1; // cur记录每次遍历的起始位置
char* s1 = NULL;
char* s2 = NULL;
if (*p2 == '\0')
return p1;
while (*cur)
{
s1 = cur;// 在原字符串中确定搜查起点,利用s1++实现从不同的起点开始,对字符串进行反复检查
s2 = p2; // 比对起点就是sour字符串,开头就是首地址
while (*s1 == *s2 && *s1 != 0 && *s2 != 0) // 相等,开始尝试检查字符串。
//同时防止都获得了\0而使得s2越界访问。
{
s1++;
s2++;
}
if (*s2 == '\0')
return cur;
cur++; // 从 cur开始的尝试匹配失败了,cur++来尝试下一个位置。
}
return NULL;
}
9.strtok 字符串切割函数
char * strtok(char * destination, char * sep)
这个函数可以在destination中查找sep中的字符,然后将sep含有的字符用\0作为标记,实现字符串的切割。这些标记会被 strtok 放在内置的一个静态变量当中 。
一次strtok只会更改一个切割字符,或者整个字符串就没有字符。
如果第一个参数不为NULL,strtok将会从 destination的开头开始搜索并且切割,并返回这个字符串的首元素地址;
如果第一个参数为NULL,strtok 将会从上一次标记(更改的地方)的下一位开始继续尝试切割,并返回上一次上一次标记的下一位的地址。
如果首如果上一次标记的是字符串的末尾,strtok 将会返回NULL.