0


深入理解《字符串》及其函数——C语言

🍁🍁🍁 猛戳订阅 👉 详解数据结构专栏 👈 深度解析 🍁🍁🍁
在这里插入图片描述

📋个人简介

  • 💬大家好,我是_奇奇,一名C/C++博主。河牧院大一在读。
  • 🔔欢迎一起交流学习
  • 💬我会将大一学的数据结构和C语言深度解析写成笔记记录下来。后期会慢慢推进。感兴趣可以订阅以下专栏。
  • 📌详解数据结构专栏🍁
  • 📌深度理解C语言专栏🍁
  • 🔑 个人主页🌳
  • 💡编程的前途是光明的,道路是曲折的。

这不是目录

❄️前言

C语言中对字符和字符串的处理很是频繁,不仅如此在以后的校招面试中字符串的题目也会涉及不少,这点在LeetCode中就能体现到,在刷题时经常会遇到处理字符串的内容,字符串还和指针相关联,对字符串的深入理解也会增加对指针的理解。

字符串函数

📌strlen

❄️功能:求字符串长度

❄️函数原型

size_t strlen ( const char* str );

🍁注意:

  • 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包含 ‘\0’ )。
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号整型,也就是不是负数。( 易错!!!

函数模拟

1.指针-指针的方式
注意:这种方式只适用于同一个数组

intmy_strlen(char*s){char*p = s;while(*p != ‘\0’ )
       p++;return p-s;}

2.计数器方法

intmy_strlen(constchar* str){int count =0;while(*str){
  count++;
  str++;}return count;}

3.递归方法(

面试官最爱考

//不能创建临时变量计数器intmy_strlen(constchar* str){if(*str =='\0')return0;elsereturn1+my_strlen(str+1);}

📌strcpy

❄️函数功能:拷贝源字符串到目的地空间,

包括"\0"也拷贝过去


❄️函数原型

char *strcpy( char *strDestination, const char *strSource );

🍁注意:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可变,原字符串不可变!

函数模拟

注意点:

  • assert断言
  • const修饰
char*my_strcpy(char*dest,constchar*src){char*ret = dest;assert(dest !=NULL);assert(src !=NULL);while((*dest++=*src++)){;}return ret;}

📌strcat

❄️函数功能:

  • 将源字符串和目标字符串连接起来。

❄️函数原型

char * strcat ( char * destination, const char * source );

🍁注意:

  • 源字符串必须以 ‘\0’ 结束。
  • 目标空间必须有足够的大,能容纳下源字符串的内容。
  • 目标空间必须可修改。
  • 返回的是目标字符串的首元素的地址。

函数模拟

注意:

置++是先使用后++。
char*my_strcat(char*dest,constchar*src){char*ret = dest;assert(dest !=NULL);assert(src !=NULL);while(*dest){
          dest++;}while((*dest++=*src++)){;}return ret;}

📌strcmp

❄️函数功能:

  • 比较两个字符串的大小,按照每个字符的ASCII码值依次往后比较,一个字符一个字符的比较,只要遇到字符不同,就返回。

❄️函数原型

char * strncpy ( char * destination, const char * source, size_t num );

🍁注意:

不是大于返回1,小于返回-1,没有这个规定

规定如下

  • 第一个字符串大于第二个字符串,则返回大于0的数字
  • 第一个字符串等于第二个字符串,则返回0
  • 第一个字符串小于第二个字符串,则返回小于0的数字

函数模拟

🍁注意;
while的循环条件&&操作符,左操作数为假时,有操作数就不用执行了。

int my_strcmp (constchar* src,constchar* dst){int ret =0;assert(src !=NULL);assert(dest !=NULL);while(!(ret =*(unsignedchar*)src-*(unsignedchar*)dst)&&*dst){++src;++dst;}if( ret <0)
    ret =-1;elseif( ret >0)
    ret =1;return( ret );}

📌strncpy

❄️函数功能:
拷贝num个字符从源字符串到目标空间。
❄️函数原型

char * strncpy ( char * destination, const char * source, size_t num );

🍁注意:

  • 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。
  • 目标空间必须足够大。
  • 和strcpy函数唯一区别就是拷贝的个数受限制。

📌strncat

❄️函数功能:
将num个源字符串和目标字符串连接起来。
❄️函数原型

char * strncat ( char * destination, const char * source, size_t num );

🍁注意:

  • 目标字符串足够大

📌strstr

函数功能:
在目标字符串str1里找到源字符串,并返回这个源字符串的首元素的地址。
函数原型

char * strstr ( const char *str1, const char * str2);

🍁注意:

  • 重点在函数模拟的实现

函数模拟

  • 如果str2为空,不用照了。直接返回str1。

如图包含了找字符串的所有情况。
思考问题要考虑全面。

我认为下面代码是最优的代码了。但是需要自己细看

。描述的话太麻烦了。
在这里插入图片描述

#include<stdio.h>#include<assert.h>char*my_strstr(constchar* str1,constchar* str2){assert(str1 && str2);if(!*str2){return((char*)str1);}char* cp = str1;char* s1 =0;char* s2 =0;while(*cp !='\0'){
        s1 = cp;
        s2 = str2;while(*s2 !='\0'&&*s1 !='\0'&&*s2 ==*s1){
            s1++;
            s2++;if(!*s2){return cp;}}
        cp++;}returnNULL;}intmain(){char arr[]="hworld";char arr1[]="world";char* p =my_strstr(arr, arr1);printf("%s", p);return0;}

📌strtok

❄️函数功能:将字符串分割。
❄️函数原型

char * strtok ( char * str, const char * sep );

🍁
注意

  • sep参数是个字符串,定义了用作分隔符的字符集合
  • 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记
  • strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  • strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  • strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  • 如果字符串中不存在更多的标记,则返回 NULL 指针。

如图例子
在这里插入图片描述

📌streeor

❄️函数功能:返回错误码所对应的错误信息。
❄️函数原型

char * strerror ( int errnum );

例子

/* strerror example : error list */#include<stdio.h>#include<string.h>#include<errno.h>//必须包含的头文件int main (){
  FILE * pFile;
  pFile = fopen ("unexist.ent","r");if(pFile ==NULL)
    printf ("Error opening file unexist.ent: %s\n",strerror(errno));//errno: Last error numberreturn0;}
Edit & Run

📌字符分类函数

函数如果他的参数符合下列条件就返回真isspace空白字符:空格‘ ’,换页‘\f’,换行’\n’,回车‘\r’,制表符’\t’或者垂直制表符’\v’isdigit十进制数字 09isxdigit十六进制数字,包括所有十进制数字,小写字母af,大写字母A ~ Fislower小写字母azisupper大写字母AZisalpha字母a~ z或AZisalnum字母或者数字,a ~ z,A Z,0~9ispunct标点符号,任何不属于数字或者字母的图形字符(可打印)isgraph任何图形字符isprint任何可打印字符,包括图形字符和空白字符iscntrl任何控制字符

内存函数

📌memcpy

❄️函数功能:

  • 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置

❄️函数原型

void * memcpy ( void * destination, const void * source, size_t num );

🍁注意:

  • 注意是以字节为单位的拷贝。
  • 这个函数在遇到 ‘\0’ 的时候并不会停下来。
  • 如果source和destination有任何的重叠,复制的结果都是未定义的。

函数模拟实现

  • 因为不知道数据是哪种类型所以需要进行强制类型转换
void* memcpy (void* dst,constvoid* src, size_t count){void* ret = dst;assert(dst);assert(src);while(count--){*(char*)dst =*(char*)src;
    dst =(char*)dst +1;
    src =(char*)src +1;}return(ret);}

📌memmove

❄️函数功能:

  • 和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。

❄️函数原型

void * memmove ( void * destination, const void * source, size_t num );

🍁注意:

  • 如果源空间和目标空间出现重叠,就得使用memmove函数处理。

函数模拟

🍁注意

  • 如果src > dest ,或者det > src+ count 从前往后拷贝就可以了
  • 否则 从后往前拷贝
  • 不遵循这个规则的话就会覆盖,导致拷贝错误。
void*memmove(void* dst,constvoid* src, size_t count){void* ret = dst;if(dst <= src ||(char*)dst >=((char*)src + count)){while(count--){*(char*)dst =*(char*)src;
            dst =(char*)dst +1;
            src =(char*)src +1;}}else{
        dst =(char*)dst + count -1;
        src =(char*)src + count -1;while(count--){*(char*)dst =*(char*)src;
            dst =(char*)dst -1;
            src =(char*)src -1;}}return(ret);}

📌memcmp

❄️函数功能:

  • 比较从ptr1和ptr2指针开始的num个字节
  • 和strcmp函数功能相同。

❄️函数原型

int memcmp ( const void * ptr1,
const void * ptr2,
size_t num );

函数返回值

在这里插入图片描述

标签: c语言 开发语言

本文转载自: https://blog.csdn.net/qq2466200050/article/details/123513571
版权归原作者 _奇奇 所有, 如有侵权,请联系我们删除。

“深入理解《字符串》及其函数&mdash;&mdash;C语言”的评论:

还没有评论