目录
长度不受限制的字符串函数
strlen
strlen函数的易错知识
strlen函数的自我实现
strcpy
strlen函数的自我实现
strcat
strlen函数的自我实现
strstr函数部分
strlen函数的自我实现
strcmp部分
长度受限制的字符串函数
strncpy
简单例子
strncat
strncmp
目录
strerror
长度不受限制的字符串函数
strlen部分
strcpy部分
strcat部分
strstr部分
strcmp部分
长度受限制的字符串函数
strncpy
strncat
strncmp
strtok
strerror
我们知道,strlen是用来求字符串长度的
它的原理就是返回字符串中的字符数,到\0为止(不包括\0),不包括NULL指针
但是这里有个易错点就是strlen的返回值是size_t,也就是无符号类型,它是永远大于等于0的,这点需要我们了解
接下来我们来道练习题加深一下印象吧
#include
#include
int main()
{
const char* str1 = "cheDCAda";
const char* str2 = "chCC";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
不知道是不是很多老铁被坑了,想当然的认为小的减去大的数目当然是<0的,如果那么想那我们还是把这里的数字当成int数据类型的了
这里就是因为strlen的返回类型是size_t,它是一直>=0的,是无符号整形,而无符号整形减去无符号整形的结果也是一个无符号整形。所以-4的符号位1不会被当成负号,而是会被翻译成2^32,那么-4就会变成一个很大的数字了。
了解后就让我们自己实现一个strlen函数吧
实现的方法有很多,有计数器,递归,指针的方法。在这里我们选择指针的方法。
int my_strlen(const char *s)//只是计算字符串长度,所以s指向的内容不需要改变,所以用const修饰
{
assert(s);//断言s不为空指针,增加代码稳健性
char *p = s;
while(*p != ‘\0’ )//寻找\0
p++;
return p-s;
}
在这里将返回类型改成int,这样可以有效规避上面无符号整形导致误判的情况
从名字我们可以知道这是个字符串拷贝函数,那么想必参数肯定要有起始的地址
他的原理其实和strlen函数类似,遇到\0就停止。
除此之外还有一些需要注意事项:源字符串必须以 '\0' 结束,不然找不到停止位置
会将源字符串中的 '\0' 拷贝到目标空间
目标空间必须足够大,确保能存放源字符串。
目标空间必须可变
了解这些后当然是来个小题看看自己是否真的掌握啦
#include
#include
int main()
{
char str1[100] = "fight\011";
char str2[100] = "xxxxxxxxx";
strcpy(str2, str1);
printf("%s", str2);
return 0;
}
大家先想想打印的结果啦
正如上面所说,遇到\0就停止。如果源字符串大于目标字符串,那肯定就会报错啦
接下来我们自己实现一下strcpy吧,我们继续加入const和assert来让我们的代码更加稳健
char* my_strcpy(char* dest, const char* src)//返回类型为char*,说明我们要返回目标空间的地址
{
char* ret = dest;//记录目标空间的起始地址
assert(dest && src);//断言都不为NULL
while ((*dest++ = *src++))
{
;
}
return ret;
}
总体来说难度还是不大的,大家有空也自己尝试敲一敲,你会发现自己的编程能力进步很大而且更清楚字符函数的使用
功能:在目标字符串后面追加源字符串的内容
函数的定义:char * strcat ( char * destination , const char * source );
注意事项:
strcat函数是找到目标字符串的\0,然后从这个位置开始往后追加源字符串的内容
清楚原理后我们继续来实现一下strcat函数吧,同样的用const与assert,使我们的代码更加稳健
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
assert(dest != NULL);
assert(src != NULL);
while (*dest)
{
dest++;
}
while ((*dest++ = *src++))
{
;
}
return ret;
}
strcat函数是从\0的位置开始,会将\0用第一个元素覆盖。那strcat能不能将自己拷贝到自己后面呢?
我们先想想然后敲出代码来证明一下我们的想法
答案是不行的,那么为什么不行呢,这时候就需要我们画图来模拟一下函数的运行过程了
找到\0
开始追加
此时src应该去找\0,可是\0已经在上面被字符a覆盖,也就是说,\0已经不复存在,程序崩溃。
功能:在目标字符串中寻找字符串是否存在
Return Value
Each of these functions returns a pointer to the first occurrence of strCharSet in string, or NULL if strCharSet does not appear in string. If strCharSet points to a string of zero length, the function returns string.
声明定义:char *strstr( const char *string, const char *strCharSet );返回目标字符串的首地址,不在目标字符串中存在的话返回NULL,如果该地址指向长度为零的字符串,则该函数返回字符串。
我们先来看看一些例子
#include
#include
int main()
{
char arr1[10]="abcdef",arr2[10]="abc,arr3[]="eee";
char*p1=strstr(arr1,arr2);
char*p2=strstr(arr1,arr3);
if(p1)
printf("不存在\n");
else printf("存在\n");
if(p2)
printf("不存在\n");
else printf("存在\n");
return 0;
}
其实这个功能有很多算法组成,其中就有很著名的KMP算法,但是KMP算法很不好理解,这里我们先用最朴素简单的思想来进行模拟实现
思路:我们先去找目标字符串str1与源字符串str2开头相等的字符,这里需要额外多一个指针记录一下目标字符串走的位置,然后两边同时往后进行比较,如果不相等就回溯。依次类推,直到str2==\0,str1!=\0的时候,那么就是找到了,如果在str2==’\0‘之前,str1已经为’\0‘,那么就是找不到
找到第一个相等的位置
两边同时向后比较
再往后p2为’\0‘,证明存在
功能:比较两个字符串是否相等,如果相等,返回0,如果不相等,比较不相等的第一个字符,如果str1>st2,返回>0的数字,如果str1
函数声明定义:int strcmp( const char *string1, const char *string2 );注意返回值为int
模拟实现
int my_strcmp (const char * src, const char * dst)
{
int ret = 0 ;
assert(src != NULL);
assert(dest != NULL);
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
其实总体类似,只是在长度不受限制的基础上多了限定的字节。
定义声明:char * strncpy ( char * destination, const char * source, size_t num );
拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
char *strncat( char *strDest, const char *strSource, size_t count );
在目标字符串后追加源字符串的前n个字节
#include
#include
int main()
{
char a[15]="hello \0 ******";
char b[15]="world";
strncat(a, b, 6);
printf("%s", a);
return 0;
}
调试可得:strncat会自动添加\0,且到\0为止,不会再去将其它字符化为\0。
功能:比较两字符串的前n个字节,返回值和strcmp一样。此处就不赘述了
char * strtok ( char * str, const char * sep );
功能:将字符串按照sep集合里的字符分割开来,将str里对应的字符变成\0。
注意事项:sep参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔 符分割的标记。
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存 它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找 下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针
其实看起来感觉十分复杂的感觉,那么接下来来个简单的例子展示一下
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main()
{
char str[] = "- This, a sample string.";
char* pch= strtok(str, " ,.-");
while (pch != NULL)
{
printf("%s\n", pch);
pch = strtok(NULL, " ,.-");
}
return 0;
}
原理:第一次进入循环的时候,strtok不为NULL,然后找到’,‘ 将其变成\0,紧接着进入第二次循环,此时strtok的参数为NULL,所以这次就从’,‘后面开始寻找在符号集合里的下一个符号,依次类推。
调试观察
功能:返回错误码,所对应的错误信息
包含头文件:#include
char *strerror( int errnum );
在c语言里,引用
#include
#include
#include //必须包含的头文件
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("Error opening file unexist.ent: %s\n",strerror(errno));
return 0;
}
看!这就将错误信息打印出来了,十分方便。
结尾
至此,字符串函数就结束了。这篇博客是总结这段时间的所学,如果能帮助到大家那真是十分荣幸,不足的地方也希望大家能评论指出,我也会多多改进,给大家继续输出更加的编程知识。