滕州网站建设企业,建设服装网站的亮点,一般做网站的在哪里找,网站首页怎么用dw做目录 前言1. strlen1.1 strlen函数的理解和使用1.2 strlen函数的模拟实现 2. strcpy2.1 strcpy函数的理解和使用2.2 strcpy函数的模拟实现 3.strcat3.1 strcat函数的理解和使用3.2 strcat 函数的模拟实现 前言
在上一篇文章中#xff0c;我们对字符分类函数和字符转换函数进行… 目录 前言1. strlen1.1 strlen函数的理解和使用1.2 strlen函数的模拟实现 2. strcpy2.1 strcpy函数的理解和使用2.2 strcpy函数的模拟实现 3.strcat3.1 strcat函数的理解和使用3.2 strcat 函数的模拟实现 前言
在上一篇文章中我们对字符分类函数和字符转换函数进行了学习部分小伙伴们可能会想字符串函数在哪里呢其实是我没有写完啦在本篇文章中我会对该内容进行详细讲解。
1. strlen
1.1 strlen函数的理解和使用
字符串函数的使用需要包含头文件string.h。strlen的返回值的类型是size_t无符号整型。strlen函数是求字符串的长度的。 例如
工作原理是 当我们有一个字符串时里面除了我们没看到的以外还存放着\0。我们给strlen函数传了数组名arr。数组名是数组首元素的地址strlen从给定的起始位置开始向后统计\0之前字符的个数。 注意 一定是从起始位置开始我们现在可以测试一下别的写法。 arr是数组名代表首元素的地址如果传arr则从a开始数。如果传arr1则跳过一个元素从b开始数。 前面我们说过strlen的返回值的类型是size_t类型的这一部分我们需要加深理解现在我们举一个例子进行理解。 按照我们的想法来看strlenarr2和strlenarr1的输出结果分别为3和63减6的值等于-3应该打印。但是运行的结果并不是我们所想因为strlen的返回值的类型是size_t , size_t类型的值相减也是size_t此时计算出的-3会被作为一个无符号的整型来处理此时的-3就没有了符号位。 在内存中存放着-3的补码当-3为无符号整型时最前面的1就不是符号位了此时就不存在原反补了。计算的结果将是一个非常大的正数所以输出的结果是。我们现在对代码进行修改。
#includestdio.h
#includestring.h
int main()
{char arr1[] abcdef;char arr2[] abc;if (strlen(arr2) strlen(arr1) )printf(\n);elseprintf(\n);return 0;
}或者
#includestdio.h
#includestring.h
int main()
{char arr1[] abcdef;char arr2[] abc;if ((int)strlen(arr2) - (int)strlen(arr1) 0)printf(\n);elseprintf(\n);return 0;
}这两个代码都能实现我们原来的目的。
1.2 strlen函数的模拟实现
我们采用递归的方式进行实现。 现在我们有一个字符数组里面存放着abcdef。现在我们需要写一个自己的函数来计算字符串的长度。仿照着strlen把arr传过去并让其返回一个size_t的值当然int也行只是字符串的长度不会为负值选择size_t比较合适。 函数的参数部分需要接受arr即首元素的地址我们采用char*类型的str进行接收同时我们不希望str去改变字符串使用可以使用const来修饰。 递归的思想是大化小我们把字符串中的第一个字符拿出来不是\0说明长度至少是11加上后面的长度就是总长度按照这个原理我们不断的向后拿取如图 代码
#includestdio.h
size_t my_strlen(const char* str)
{if (*str \0)return 0;elsereturn 1 my_strlen(str 1);
}int main()
{char arr[] abcdef;size_t len my_strlen(arr);printf(%zd\n, len);return 0;
}运行结果
现在可能还有部分小伙伴没有理解我们可以缩短字符串的长度改为abc来理解
我们要计算abc的长度此处我们调用了自己写的函数来完成。我们将a的地址传了过去给了str此时str向后就可以看到a b c \0。 刚开始时* sr 为aa并不等于\0我们就走else这条路然后再对my_strlen进行调用。第二次调用时这里的str指向bb不等于\0走else的路线这里我们还需要对my_strlen进行调用第三次调用时这里的str指向cc不等于\0走else的路线最后一次调用my_strlen时str指向了\0。此时我们的递推就结束了将开始回归。1就会不断的相加到3最后返回去此时len就为3. 注意 在这里的 1 my_strlen(str 1)没有返回时是不会计算的。 代码
#includestdio.h
size_t my_strlen(const char* str)
{if (*str \0)return 0;elsereturn 1 my_strlen(str 1);
}int main()
{char arr[] abc;size_t len my_strlen(arr);printf(%zd\n, len);return 0;
}2. strcpy
2.1 strcpy函数的理解和使用
该函数是用来进行字符串拷贝的。我们现在来看函数的基本情况。 第一个参数的名字是destination目的地。第二个参数是source源头即将源头的数据拷贝到destination里面去。例如 理解 arr1数组里面放了hello world\0 .我们把arr1和arr2分别传给了我们刚才说的source和destination我们认为它是一个个字符进行拷贝的把\0拷贝完成就停止。 这里我们可以看看到底有没有将\0拷贝过去如下 此时我们可以看到\0也被拷贝过去了。既然我们需要将\0拷贝过去那么我们源头中的字符串也需要有\0。如果我们去掉\0会发生什么呢如下 拷贝将不会有停下的动作一直进行拷贝甚至会越界往后进行修改。 注意
在拷贝时我们的目标空间必须足够大只有足够大才能放下从源头拷贝过来的数据目标空间必须可修改如图 这里的p是常量字符串不能进行修改。
2.2 strcpy函数的模拟实现
我们首先创建arr1里面放上abcdef再创建一个arr2里面可以放上20个元素。根据刚才学到的strcpy的参数部分我们也可以将my_strlen中的参数设置为char * dest 和char * src。暂时我们把返回这里写为void。 我们将arr2和arr1传过去之后dest和src分别指向如下位置 这里我们需要将字符一个个拷贝过去即我们需要进行多次拷贝我们可以写一个while循环在里面使dest和src来不停的往后。当\0也拷贝下来时循环结束所以我们把条件写为 * src ’\0’,此时\0并没有拷贝下来我们添加 *dest * src即可停下来时 * src为\0我们此时相当于把‘\0’拷贝过去。此时代码就完成了。
代码
#includestdio.h
void my_strcpy(char* dest, char* src)
{while (*src ! \0){*dest *src;src;dest;}*dest *src;
}int main()
{char arr1[] abcdef;char arr2[20] { 0 };my_strcpy(arr2, arr1);printf(%s\n,arr2);return 0;
}运行结果 现在我们进行优化把代码的改为后置用完后再然后我们的 * dest * src和 * dest * src是有一点重复的我们需要改为如下写法
#includestdio.h
void my_strcpy(char* dest, char* src)
{while (*dest *src){;}
}int main()
{char arr1[] abcdef;char arr2[20] { 0 };my_strcpy(arr2, arr1);printf(%s\n,arr2);return 0;
}理解 第一次 * src是a我们将a赋值过去此时整个表达式的值就为aa的ASCII码值不为0为真进入循环因为赋值完成以后进行则下一次 * src拿到的值就是b然后再进行该过程直到 * src指向\0将\0赋值过去此时表达式的结果为\0\0的ASCII码为00为假跳出循环。我们会发现这里我们既可以赋值赋值产生的值有可以进行判断。 我们还可以对代码进行调整我们的目的是将src指向的内容拷贝到dest指向的空间里面去我们不希望src指向的空间被修改。这里可以加const进行修饰但是解引用之前我们害怕为空指针我们可以利用assert断言进行处理。
代码
#includestdio.h
#includeassert.h
void my_strcpy(char* dest, const char* src)
{assert(dest src);while (*dest *src){;}
}int main()
{char arr1[] abcdef;char arr2[20] { 0 };my_strcpy(arr2, arr1);printf(%s\n,arr2);return 0;
}但是strcpy的返回值的类型是char*与我们自己写的函数是不同的那使用char * 有什么好处吗 函数是将原字符串拷贝放到目标空间里面去我们是期望目标空间发生变化来进行观察。所以函数最终返回目标空间的起始位置。但是我们这里不能直接return dest。因为这里dest不断地以后dest指向的不再是起始地址解决方式是我们创建一个 char * 的ret把未进行改动的dest存一份最后return ret。
代码
#includestdio.h
#includeassert.h
char* my_strcpy(char* dest, const char* src)
{char* ret dest;assert(dest src);while (*dest *src){;}return ret;
}int main()
{char arr1[] abcdef;char arr2[20] { 0 };char* ret my_strcpy(arr2, arr1);printf(%s\n,ret);return 0;
}运行结果 此时我们的函数更加灵活my_strcpy的返回值也可以作为其他函数的参数实现链式访问。
代码
#includestdio.h
#includeassert.h
#includestring.h
char* my_strcpy(char* dest, const char* src)
{char* ret dest;assert(dest src);while (*dest *src){;}return ret;
}int main()
{char arr1[] abcdef;char arr2[20] { 0 };/*char* ret my_strcpy(arr2, arr1);*/size_t len strlen(my_strcpy(arr2, arr1));printf(%zd\n,len);return 0;
}
运行结果
3.strcat
3.1 strcat函数的理解和使用
该函数的作用是字符串的追加我们直接上实例进行理解
我们现在有一个数组arr1里面存放着hello。我们想在后面追加world。可能有同学会想用strcpy但是它会将hello给覆盖。所以以我们会使用strcat这个函数。
现在我们研究一下这个函数 我们不难发现这与我们刚才看到的strcpy的参数是一样的第一个参数是char * destination是我们需要追加的对象第二个参数是const char * source是需要追加的内容。这个函数的返回值的路线是char *返回的是目标空间的起始地址与我们之前讲的strcpy一样。 我们现在看看是如何追加的 这里是在第一个\0的位置开始追加world我们不免会想这里我们是将world的\0追加过来了还是原来在arr1中的我们可以测试看看我们可以在原arr1中添加一个\0并观察试试。 两张图对比我们可以发现world从hello后面的\0开始追加world还把它原来的\0也带了过来。
strcat的原理
找到目标空间中的第一个\0然后从这个\0的位置开始追加源头字符串源头字符串的内容包括\0都会追加到目标空间
注意: 在追加时目标空间的大小要足够长能够放下我们要追加的数据。其次目标空间要可修改以便追加数据。因为会将源头字符串字符串的\0追加过去所以我们的源头字符串要有\0。目标字符串也要有\0不然不知道从哪里开始追加。
3.2 strcat 函数的模拟实现
我们之前观察过它的参数和返回类型这些部分是和strcpy一样的。我们就可以仿照来写代码。 我们首先需要在目标空间中找到\0再进行追加这里我们可以利用while循环往后找如果 * dest不等于\0,我们就让dest直到dest指向\0跳出循环。 之后我们需要将world这个数据拷贝过去 这个拷贝数据的代码我们观察已经学习过了我们可以照搬过来。刚才dest已经指向了\0现在我们进行拷贝就会将\0覆盖。 接下来我们要返回char * 的数据即返回目标空间的起始地址但是我们的dest通过已经走很远了我们可以仿照刚才的ret来存放目标空间的起始地址最后返回ret。当然如果担心我们的指针有效性也可以采用assert断言一下。
代码
#includestdio.h
#includeassert.h
char* my_strcat(char* dest, const char* src)
{char* ret dest;assert(dest src);while (*dest ! \0)dest;while (*dest *src){;}return ret;
}int main()
{char arr1[20] hello ;my_strcat(arr1, world);printf(%s\n, arr1);return 0;
}运行结果 思考 我们能不能自己给自己追加 进行传参以后我们的dest和src指向的位置为
程序开始运行以后我们的dest会一直往后找直到找到\0之后开始拷贝此时h就会将原来的\0覆盖没有\0以后拷贝的这个循环是停不下来的,就会造成死循环的问题。 所以我们通常是不会用这个函数进行对自己追加的操作的。strcat在进行自己给自己追加时会有一定的概率会成功我们如果想要自己给自己追加可以使用strncat。 好了今天知识就学习到这里我们下期blog再见如果文章内容有误请大佬在评论区斧正谢谢大家