要介绍的有关于字符串的库函数(含有函数的实现)
一.求字符串长度:
strlen
size_t strlen ( const char * str);//括号当中传入首元素地址
1.从字符串首元素开始,遇到“\0”就停止,每经过一位就+1,即返回的是\0以前字符的个数。
2.返回值是无符号整形size_t,不可能是负数。
3.参数指向的字符串必须是以\0为结束的。
4.strlen函数的模拟实现。
例1:简单计算字符串长度
int main()
{
size_t len = strlen("abcdef");
printf("%u\n",len);//打印size_t类型的返回值用%u。
char arr[] = "abcdef";
printf("%u\n",strlen(arr));
return 0;
}
运行结果:
例2:强化了解返回值是无符号整形
解析:当不知道返回值是无符号整型的时候,会认为括号的值小于0,打印heheh.无符号整型都是正数,所以打印hahah.
如果整的想要利用strlen计算,打印heheh的目的,那么将返回值类型强制转换为int类型。如下:
例3:参数指向字符串要以\0为结束
解析:由于声明的arr当中未表明\0的位置,所以strlen会继续读取接下来的字符,直到找到\0,所以出现在的是一个随机值。
例4:函数的模拟实现
int my_strlen( const char *arr)
{
int count = 0;
while (*arr++ != NULL)
{
count++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
int ret=my_strlen(arr);
printf("%d\n",ret);
return 0;
}
二.长度不受限制的字符串函数:
strcpy
注意:在某些编译器中可能会报错,所以要加上:#define _CRT_SECURE_NO_WARNINGS
char* strcpy(char * destination, const char * source );
1.返回值是char类型,(目标字符串,需要复制的字符串)。使用时需要引用string.h文件。
2.会以\0作为结束的标志,所以原字符串必须含有\0作为结束的标志。
3.会将原字符串中的\0拷贝到目标空间。
4.目标空间要足够大,才能容纳原字符串。
5.目标空间要可改变。
6.strcpy的模拟实现。*
例1:函数的简单实用
例2:会将原字符串中的\0也打印
通过调试当中的监视,我们可以看到\0的拷贝。
例3:函数的模拟实现:
char* my_strcpy(char* dest,const char* src)//返回一个char*类型的指针,通过指针找到改变的字符串
{
char* ret = dest;//在后续进行当中指针大小发生改变,但是返回时我们只需要开头的指针
while(*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "xxxxxxxxxxxxxx";
char arr2[] = "abcdef";
char* ret=my_strcpy(arr1,arr2);
printf("%s\n",ret);
}
strcat
说明: 函数用于追加,连接字符串。
char * strcat ( char * destination, const char * source );
1.源字符串必须以 ‘\0’ 结束。
2.目标空间必须有足够的大,能容纳下源字符串的内容。
3.目标空间必须可修改
例1:函数练习使用:
int main()
{
//注意这里要开辟好足够的空间
char arr1[20] = "abc";
strcat(arr1,"def");
printf("%s\n",arr1);
return 0;
}
例2:arr1后面没有\0,导致无法停止出错。
函数的模拟实现:
模拟实现:
#include<assert.h>
char *my_strcat(char *dest, const char*src)
{
char *ret = dest;
assert(dest != NULL);
assert(src != NULL);
//找到目标字符串的末尾\0的位置,让源字符串开头替换\0
while(*dest)
{
dest++;
}
while((*dest++ = *src++))
{
;
}
return ret;
}
strcmp
比较字符串,比较的是字符串的内容,不是长度。一对字符一对字符进行比较。
int strcmp ( const char * str1, const char * str2 );
返回类型是int,整形。
比较两个字符串是否相同,逐个字符进行比较,根据字符的ASCII码值进行比较。
标准规定:
1.第一个字符串大于第二个字符串,则返回大于0的数字
2.第一个字符串等于第二个字符串,则返回0
3.第一个字符串小于第二个字符串,则返回小于0的数字
4.遇到\0就停止,不相同判断出大小之后就停止,不管出没出大小结果。
例1:函数的简单应用
例2:函数的实现(1)
int my_strcmp(const char* arr1, const char* arr2)
{
while (*arr1 != '\0' && *arr2 != '\0')
{
if (*arr1 > *arr2)
{
return 1;
}
else if (*arr1 < *arr2)
{
return -1;
}
else
{
arr1++;
arr2++;
}
}
//验证两个字符串是否一样长,前面都相同的情况下,谁长谁大
if (*arr1 != '\0')
return 1;
if (*arr2 != '\0')
return -2;
else
return 0;//如果循环结束并且仍未分出大小,并且二者一样长,说明两个字符串相同
}
int main()
{
char arr1[]="abcdefd";
char arr2[]= "abcde";
int ret= my_strcmp(arr1,arr2);
printf("%d\n",ret);
return 0;
}
结果如下:
函数实现(2)
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 );
}
函数的实现(3)
int my_strcmp(const char*str1,const char *str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
return *str1 - *str2;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abcq";
int ret=my_strcmp(arr1,arr2);
if (ret > 0)
{
printf("arr1>arr2");
}
else if (ret < 0)
{
printf("arr1<arr2");
}
else
printf("arr1=arr2");
return 0;
}
三 长度受限制的字符串函数介绍:
strncpy
char * strncpy ( char * destination, const char * source, size_t num );
1.拷贝num个字符从源字符串到目标空间。
2.如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
3.最后的是需要拷贝的字符个数.相对来说更安全一点,就会考虑到目标函数的大小问题容纳问题。
例1:函数的简单应用
例2:如果填写的字符串个数超过本身字符串个数,他会自动用\0来进行拷贝替换,如图所示:
strncat
char * strncat ( char * destination, const char * source, size_t num );
例1:字符串追加限定个数:
int main()
{
//为了方便观看连接的时候是否会替换原字符串的\0,以及是否会将源头字符串的\0拷贝进去
char arr1[20] = "abc\0xxxxx";
char arr2[] = "defg";
strncat(arr1,arr2,3);
return 0;
}
注意:当追加字符串的个数大于字符串本身具有的个数时,只会到本身拥有的字符串个数到\0就停止,如图所示:
strncmp
int strncmp ( const char * str1, const char * str2, size_t num );
例1:简单应用:
四 字符串查找:
strstr
char * strstr ( const char *, const char * );
1.应用:在一个字符串当中查找是否存在另一个字符串,
2.原理:查找第一个所需要查找的字符串,就会返回这样字符串第一个的地址。
如果找不到字符串就会返回空指针。
例1:应用简介如下
例2:函数的实现:
#include<assert.h>
char* my_strstr(const char* str1,const char* str2)
{
assert(str1&&str2);
char* s1;
char* s2;
char* cp=str1;
//如果所要查找的字符串是一个空指针,直接返回cp地址
if (*str2 == '\0')
return cp;
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 == *s2 && *s1 != '\0' && *s2 != '\0')
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
//找不到
return NULL;
}
int main()
{
char arr1[] = "i am a good student,hehe student";
char arr2[] = "student";
char *ret= my_strstr(arr1,arr2);
if (ret == NULL)
{
printf("找不到");
}
else
printf("%s\n",ret);
return 0;
}
strtok
char * strtok ( char * str, const char * sep );
1.sep参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
3.strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改
变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
4.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
5.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
6.如果字符串中不存在更多的标记,则返回 NULL 指针。
例1:
五 错误信息报告:
strerror
strerror: 打印出错误信息
同类另一个->perror: 打印内容+错误信息
char * strerror ( int errnum );
1.函数能够返回c语言内置错误码对应的错误信息。
2.函数返回值是错误码对应的错误信息字符串的首元素地址。
3.必须包含的头文件
#include <stdio.h>
#include <string.h>
#include <errno.h>
简单应用:
六 内存操作函数
memcpy
void * memcpy ( void * destination, const void * source, size_t num );
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。 2.这个函数在遇到 ‘\0’ 的时候并不会停下来。 3.如果source和destination有任何的重叠,复制的结果都是未定义的 模拟函数实现:
void * memcpy ( void * dst, const void * src, size_t count)
{
void * ret = dst;
assert(dst);
assert(src);
/*
* copy from lower addresses to higher addresses
*/
while (count--)
{
*(char *)dst = *(char *)src;
dst = (char *)dst + 1;
src = (char *)src + 1;
}
return(ret);
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
memcpy(arr,arr+2,16);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
memmove
说明:实现了字符串重复拷贝,拷贝的地方可以有重叠。
void * memmove ( void * destination, const void * source, size_t num );
1.和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
2.如果源空间和目标空间出现重叠,就得使用memmove函数处理。
3.memmove(所要挪动到的地方,从哪里开始,字节大小)
例子:
函数实现:
为了避免出现分析memcpy中出现可能的重叠部分更替,思路是如果向后面移动拷贝,就从字符串的后面开始想字符串前面拷贝;如果想字符串前面进项拷贝移动,就从字符串前面开始向后面开始一个个拷贝移动。(具体注意事项在代码中有注释)
void* my_memmove(void* dest,const void*src,size_t count)//无符号整形
{
assert(dest&&src);
void* ret = dest;
if (dest >= src)//说明就是向后的进行,要从后往前进行
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
//加的count就是原来个数-1了,正好是最后的指针
//强制类型和转换为char*类型,一个字节一个字节移动。
}
}
if (dest < src)//说明向前进行,所以要先拷贝前面的
{
while (count--)
{
*(char*)dest=*(char*)src;//将元数据当中一个字节的数据给到前面的一个字节
dest = (char*)dest + 1;//根据数据在内存当中的存储01 00 00 00 02 00 00 00。一个字节一个字节给
src = (char*)src + 1;
}
}
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
my_memmove(arr,arr+2,16);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++)
{
printf("%d ",arr[i]);
}
return 0;
}
memset
用于初始化内存空间为单个内容。
说明:memset(目标空间,初始化内容,每一个单位是字节)
int main()
{
int arr[] = {1,2,3,4,5};
memset(arr,0,20);//将内存当中的数组数字都初始化为0
return 0;
}
初始化之前内存存储:
全部初始化为0:
memcmp
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
1.比较的num是字节大小。
2.返回值类型:
如果ptr1>ptr2,返回1.
如果ptr1<ptr2,返回2.
如果ptr1=ptr2,返回0.
例子:
完结,撒花!欢迎各位点赞转发互关哈!