strlen
size_t strlen( const char* str )
作用:是计算字符串的字符个数
原理:是计算字符串在'\0'前出现的字符个数('\0'是字符串结束的标志)
返回类型是size_t,因为strlen求字符个数不管怎样得到的都是正整数。
(用size_t的缺点:两个size_t类型的数相减时,因为类型是size_t,所以结果必定是正整数,必要时要用强制类型转换)
const char* str,const修饰的是*p,也就是p所指向的字符串的值不能变。(不能通过p这个指针去改str的值,str的值还是能修改的)(如果不要改变字符串,习惯在*p前加上const)
如果是char*const str,const修饰的是指针变量p,就是p所指向的地址不能变。
使用方法:
char arr[] = "abcdefg";
int ret = strlen(arr);
创建了个数组放字符串,数组元素[a,b,c,d,e,f,g,\0],arr是数组首元素地址,也就是字符串地址,strlen会从得到的地址开始往后走,直到走到\0,然后计算走过的字符个数,ret就是字符个数。
模拟再现
1.用循环的方式
int my_strlen(const char* str)
{
assert(str != 0);
int count = 0;
while (*str)
{
str++;
count++;
}
return count;
}
(assert是用于检测指针是否是空指针,如果是空指针就会报错)
每经过一个字符,就会判断是否是0('\0'),如果不是,就继续向下走,同时计数加一。
2.用递归的方式
int my_strlen(const char* str)
{
assert(str != 0);
if (*str != '\0')
{
return 1 + my_strlen(str+1);
}
else
{
return 0;
}
}
如果不是'\0',就返回1加上(下一个地址是否为'\0',否,加一)
3.指针-指针
int my_strlen(const char* str)
{
assert(str != 0);
const char* start = str;
while (*str)
{
str++;
}
return str - start;
}
和第一种方法类似,只不过这次就不会走一步记一个数,而是一直走到'\0',然后拿走到'\0'的地址减去开始的地址,指针-指针得到的是中间的元素个数(char类型),就会的到中间的字符个数。
strcpy
char* strcpy(char*str1 , const char*str2)
作用:字符串拷贝,前一个str1是目标,后一个str2是源头,把源头空间的字符串拷贝到目标空间。
原理:从源头空间开始找,直到找到'\0',停止,然后把源头空间的字符串连同'\0'一起拷贝到目标空间。返回的是目标空间的首元素地址
要求:1.源数据一定要有'\0',否则无法判断要拷贝的字符串结尾在哪。2.目标空间必须足够大,能放的下从源空间拷贝过去的字符。3.目标空间大小必须可变。
使用方法:
char arr1[20] = "";
char arr2[] = "abcdef";
strcpy(arr1, arr2);
printf("%s\n", arr1);
打印出来的结果是:abcdef.
模拟再现:
char *my_strcpy(char* str1, const char* str2)
{
char* ret = str1;
assert(str1 && str2);
while (*str1++ = *str2++)
{
;
}
return ret;//返回目标空间首元素
}
ret就是目标空间首元素地址,在while循环的判断条件中,同时完成了字符的复制,以及当str2到达'\0'即*str2=0,就会自动停下(判断条件为0,是假)
strcat
char* strcat (char* str1,const char*str2)
作用:对目标空间追加源空间的内容
原理:找到目标空间'\0'处,作为追加的开始地点,源空间的'\0'处作为追加内容的结束点,把源空间的追加内容,加到目标空间的'\0'处(会覆盖'\0')
要求:目标空间和源空间都要有'\0',目标空间要足够大且可修改大小。
使用方法:
char arr[20] = "abcd";
strcat(arr, "cccsss");
printf("%s\n", arr);
结果是abcdcccsss(在abcd后面加上了cccsss)
模拟再现:
char* my_strcat(char* str1, const char* str2)
{
assert(str1 && str2);
char* ret = str1;
//1.找目标空间的\0
while (*str1 != '\0')
{
str1++;
}
//2.追加
while(*str1++=*str2++)
{
;
}
return ret;
}
目标空间从头开始找'\0',找到了'\0',的地址,就从这里开始追加源空间的字符串,直到源空间找到'\0'
strcmp
int strcmp(const char*str1,const char*str2)
作用:用于比较两个字符串的大小
原理:不是比较字符串的长度,而是从头开始一个一个比较字符的ascill码值,
str1>str2,返回一个>0的正数,
str1<str2,返回一个<0的负数,
str1=str2,返回0。
(在vs环境下,这个>0和<0,返回的是1,-1,但是其他的编译器可能不是这样的)
使用方法:
char arr1[] = "abcdef";
char arr2[] = "abcd";
int ret =strcmp(arr1, arr2);
printf("%d", ret);
这里可以把这两个字符串想象成两个数,比大小从最高位往下看,a是它们的最高位,最高位相同,看下一位,b是第二高位,第二位也相同,看第三位......第五位,arr1是e,arr2是0,e的ascill码值大于0,就不用看更低的位了,arr1>arr2。如果arr2是abcdf,在第五位arr1的e小于arr2的f,就是arr1<arr2。
模拟再现
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)//从最高位往下找找到不同的那一位(那个地址)
{
if (*str1 == '0')//如果位数相同,又相等,可能会同时到空的0(没字符的地方),这个时候就要停下来了,不能再继续找不同的地方了。
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
return 1;
else
return -1;
//return *str1-*str2;
//别的编译器下的情况,不是所有编译器返回值是1,-1。
}
strcpy
strcat
strcmp
这三个是长度不受限制的字符串函数,会不安全,想要限制长度,用下面下面三个。
strncpy
char* strncpy(const char*str1,const char*str2,size_t num)
和strncpy一样,只不过后面多出了size_t num,num是选择要拷贝几个字符
若num大于源空间中的字符数,就会拿'0'来补齐,再拿去拷贝到目标空间。
strncat
char* strncat(char*str1,const char*str2,size_t num)
可选择 追加内容选源空间中的几个字符,不够拿'0'凑
strncmp
int strncmp(const char*str1,const char*str2,size_t num)
可选择 比较的字符串长度是多少
strstr
char* strstr (const char*str2,const char*str2)
作用:在str1中查找str2第一次出现的位置。(查找子字符串)
返回的是 str1中第一次找到str2的地址 (指针)
模拟再现
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 && str2);
if (*str2 == '\0')
return str1;
const char* s1 = str1;
const char* s2 = str2;//str1,str2各给一个指针
const char* cp = str1;//str1再给个指针
while (*cp)//在str1一步一步找,找到\o前,一直循环
{
//每次循环进去
s1 = cp;
s2 = str2;
while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)//找到str1,str2相同的地方,开始核对str2剩下的字符能否对的上
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;//没找到str1中的一个字符(cp)和str2首字符(s2)相同的地方,str1向前推进一位
}
return NULL;
}
strtok
char* strtok(char*str,const char*sep)
作用:通过sep中的分隔符切分字符串
char arr[]="yuqi@gmail.com";
char*p="@.";
strtok(arr,p)
其中@和.是分隔符,放在p中
找到第一个分隔符处,把它替换成\0,如果第一个参数是NULL,会从上一次\0处,继续开始找下一个分隔符切割(这个函数会改变字符串,同时也会在函数里记录字符串中的一些地址(变成\0的地方))
返回的是被分隔的第一串字符串的地址
一般用法:
strcpy(buf,arr);//会改变字符串,用临时的buf来实现效果,这样就不会改到arr上了
for(ret=strtok(buf,p);ret!=NULL;ret=strtok(NULL,p))
{
printf("%s\n",ret);
}
结果:
yuqi
gmail
com