目录
前言
函数介绍
strlen
strcpy
strcat
strcmp
strncpy
strncat
strncmp
strstr
strtok
总结
前言
感谢您阅读我的博客。在本期文章中,我将为您介绍一些常用的字符和字符串处理函数,并提供一些注意事项和实现方法。
本期我们将会对以下库函数进行重点介绍以及模拟实现,其他的我们也会介绍使用方法以及注意事项。
求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
内存操作函数
memcpy
memmove
函数介绍
strlen
函数原型:
size_t strlen ( const char * str );
字符串以 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0')。
参数指向的字符串必须要以 '\0' 结束。
注意函数的返回值为size_t,是无符号的( 易错 ),我们在使用strlen函数时要格外注意,例如以下代码:
int main()
{
const char* str1 = "abcdef";
const char* str2 = "aaa";
if (strlen(str2) - strlen(str1) > 0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
我们可以判断出str1长度是大于str2的,可是最终的输出为:str2>str1,这是因为size_t,是无符号的,两个无符号的数据进行相减,最终结果也会是无符号的。
所以在使用的过程中要格外注意,避免这样直接做差来判断字符串(可以将类型转换为int类型再做差),视情况而定。
strcpy
函数原型:
char* strcpy(char * destination, const char * source );
strcpy函数的作用是字符拷贝,destination为目标字符串,source为源字符串,将字符串source拷贝到destination目标字符串。
另外在使用时我们还要注意以下几点:
- 源字符串必须以 '\0' 结束。
- 会将源字符串中的 '\0' 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可修改
- 目标空间必须可修改,举个例子:
int main()
{
char arr1[] = "Hello world!";
char* arr2 = "xxxxxxxxxxxxxxxxxxx";
printf("%s\n", strcpy(arr2, arr1));
return 0;
}
这里的arr2确实指向一个字符串,但arr2的字符串属于常量字符串是不可以修改的。那么这样使用必然会使程序崩溃。
strcat
函数原型:
char * strcat ( char * destination, const char * source );
strcat函数的作用是连接两个字符串 ,将source这个源字符串追加到destination目标字符串的末尾。
注意事项:
- 源字符串必须以 '\0' 结束,连接的过程中会将源字符串末尾的\0一同拷贝过去,作为字符串结束标志。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。
- 同一个数组字符串不可以自己给自己追加。即
strcat(arr, arr);
在某些编译器上或许能够运行成功,但是会出现使用未初始化的内存空间这样的警告,这样的操作是很危险的,所以还是建议尽量不要这样去用,至于为什么我会在模拟实现的时候向大家介绍原因。
strcmp
函数原型:
int strcmp ( const char * str1, const char * str2 );
strcmp的作用时比较两个2字符串大小。
比较规则:
- 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
那两个字符串是如何比较的呢?
strcmp函数会逐个比较两个字符串对应位置上的字符的ASCII码大小,直到遇到不相等的字符或者遇到字符串结束符'\0'。如果遇到不相等的字符,则返回两个字符的ASCII码差值;
我们来举例使用一下:
int main()
{
int ret = strcmp("abcdef", "abc");//1
int ret1 = strcmp("abcdef", "bbc");//-1
int ret2= strcmp("abc", "abc");//0
return 0;
}
- 第一个比较,前三个字符相等到第四个字符对应位置进行比较,d和\0进行比较,‘d’>‘\0’所以返回大于0的数。
- 第二个,两字符串第一个字符就不一样,那就对第一个字符进行比较,‘b'>‘a’所以返回小于0的数-1.
- 第三个,两字符串相等,返回0。
strncpy
函数原型:
char * strncpy ( char * destination, const char * source, size_t num );
作用:
- 拷贝num个字符从源字符串到目标空间。
- 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
我们举例使用一下:
int main()
{
char arr[20] = "abcdef";
char arr1[] = "xxxxxxxxxxxxxxxx";
strncpy(arr, arr1, 3);
return 0;
}
通过调试我们发现也确实只拷贝过去了三个。除此之外还有我们的strncat和strncmp
strncat
函数原型:
char * strncat ( char * destination, const char * source, size_t num );
规则如下:
- 将源字符串src的前n个字符(或者直到遇到源字符串的结束符'\0')追加到目标字符串dest的末尾
- 追加完成后,目标字符串dest的末尾会自动添加一个结束符'\0
使用实例:
int main()
{
char arr[20] = "abcdef";
char arr1[] = "xxxxxxxxxxxxxxxx";
strncat(arr, arr1, 3);
return 0;
}
将3个xxx添加到abcdef后边。
strncmp
函数原型:
int strncmp ( const char * str1, const char * str2, size_t num );
str1和str2是要比较的两个字符串,num是要比较的最大字符数。
比较规则和strcmp规则相同。
使用实例:
int main()
{
char arr[] = "abcdef";
char arr1[] = "abddd";
printf("%d",strncmp(arr, arr1, 3));
return 0;
}
strstr
函数原型:
char * strstr ( const char *, const char * );
作用:用于在一个字符串中查找指定子串的第一次出现位置。
规则如下:
- 在字符串中查找子串的第一次出现位置。
- 如果找到了子串,则返回指向该位置的指针。
- 如果未找到子串,则返回NULL。
使用实例:
int main()
{
char a[] = "abcdefjhidef";
char b[] = "def";
printf("%s", strstr(a, b));//defjhidef
return 0;
}
strtok
函数原型:
char * strtok ( char * str, const char * sep );
这个函数有点奇怪,和我们平常使用的库函数都有所不同,这个函数的作用是切割字符串,具体怎么切割,规则如下:
- 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
- strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
- strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
- strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
- 如果字符串中不存在更多的标记,则返回 NULL 指针。
什么意思呢?接下来我会用代码向大家展示:
int main()
{
char arr[] = "hello$world@haha";
char tarr[30];
strcpy(tarr, arr);
char sep[] = "$@";
char* ret=strtok(tarr, sep);
printf("%s", ret);//hello
return 0;
}
这段代码的输出是hello,sep是一个存放分割标记的数组,当在数组tarr中检查到sep中的字符时,strtok函数就会将该字符替换成\0,并返回到起始位置(字符串首元素地址处)。
如果再次调用该函数,传进去一个空指针:
int main()
{
char arr[] = "hello$world@haha";
char tarr[30];
strcpy(tarr, arr);
char sep[] = "$@";
char* ret=strtok(tarr, sep);
ret = strtok(NULL, sep);
printf("%s", ret);//world
return 0;
}
它的输出就是world,从第一个切割标记的字符$那里开始,查找下一个标记处,将标记改位\0,返回本次函数调用标记的起始位置。直到遇到\0为止,返回一个空指针。
在使用时我们也可以这样使用:
int main()
{
char arr[] = "hello$world@haha*666";
char tarr[30];
strcpy(tarr, arr);
char sep[] = "$@*";
char* ret = NULL;
for (ret = strtok(tarr, sep); ret != NULL; ret = strtok(NULL, sep))
{
printf("%s\n", ret);
}
return 0;
}
将ret=strtok(tarr, sep);作为初始值标记第一个分割点,ret != NULL;作为条件,ret = strtok(NULL, sep)作为自增量,这样不管我们是否知道需要分割的字符串被分割的次数,都可以将字符串根据自己的需求进行分割。
memcpy
函数原型:
void * memcpy ( void * dest, const void * src, size_t n );
作用:将指定长度的数据从源内存地址复制到目标内存地址。dest是目标内存地址,src是源内存地址,n是要复制的字节数。
规则如下:
- 将源内存地址src中的前n个字节的数据复制到目标内存地址dest中。
- 如果源内存地址和目标内存地址有重叠,复制的结果是不确定的。
就是说如果将一个数组的片段,复制给同一个数组,就可能会导致复制重叠,无法达到我们预期的结果,不同的编译器结果可能也不相同。
例如:
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
memcpy(arr + 2, arr, 20);
这样写可能会导致复制结果出错,建议不要这样去使用。
使用实例:
#include<string.h>//使用memcpy函数要引用头文件
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int arr1[20] = { 0 };
memcpy(arr1, arr, 20);
for (int i = 0; i < 20; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
memmove
函数原型:
void * memmove ( void * destination, const void * source, size_t num );
使用规则如下:
- 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
- 如果源空间和目标空间出现重叠,就得使用memmove函数处理
使用实例:
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
memmove(arr + 2, arr, 20);
for (int i = 0; i < 10; i++)
{
printf("%d ", arr[i]);//1 2 1 2 3 4 5 8 9 10
}
return 0;
}
memcmp
函数原型:
int memcmp ( const void * ptr1, const void * ptr2, size_t num )
作用:
比较两个内存区域的内容是否相等。
其中ptr1和ptr2是要比较的两个内存区域的起始地址,num是要比较的字节数
比较规则如下:
- 比较两个内存区域的前n个字节的内容。
- 如果两个内存区域的内容相等,返回0。
- 如果两个内存区域的内容不相等,返回两个不相等字节的差值(按字节的无符号比较)
需要注意:
memcmp函数比较的是字节内容,而不是字符内容。因此,对于包含非字符数据(如结构体、数组等)的内存区域,也可以使用memcmp进行比较。
使用实例:
int main()
{
int arr[] = { 1,2,1,4,5 };
int arr1[] = { 1,2,257 };
int ret=memcmp(arr, arr1, 9);
printf("%d", ret);//0
return 0;
}
我们比较前9个字节的内存返回值为0,说明两数组前9个字节的内容相等。
通过调试我们也可以观察到:
文章来源:https://www.toymoban.com/news/detail-560735.html
总结
好的文章到这里内容到此就结束了,在学习字符和字符串处理函数的过程中,我们不仅需要掌握其使用方法,还需要了解其背后的原理和细节。希望本篇文章能够激发您对字符和字符串处理的兴趣,让您深入探究其中的奥秘。最后,感谢您的耐心阅读。如果您想了解更多关于字符和字符串处理的知识,请继续关注我的博客,下期我将对一些基本的库函数进行模拟实现。文章来源地址https://www.toymoban.com/news/detail-560735.html
到了这里,关于探索字符与字符串:基本库函数的使用(一)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!