当前位置:网站首页>【C语言】字符串函数及模拟实现strlen&&strcpy&&strcat&&strcmp
【C语言】字符串函数及模拟实现strlen&&strcpy&&strcat&&strcmp
2022-07-05 19:09:00 【平凡的人1】
作者:@平凡的人1
专栏:《C语言从0到1》
一句话:凡是过往,皆为序章
说明: 过去无可挽回, 未来可以改变
前言
我们知道,在C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的(不像其他语言直接String即可解决),在C语言中字符串通常放在常量字符串中或者字符数组中。
字符串常量适用于那些对它不做修改的字符串函数。
我们这次主要介绍的就是一些字符串函数。
- 关于学习一些陌生的函数:我们可以通过cplusplus.com进行了解学习,知道参数所代表的含义以及实现的功能是上面,这可以让我们事半功倍!对于英文不理解的话,我们可以翻译成自己熟悉的中文啦。
- 一定要自己多动手去实现代码哦,也不要一口气吃成胖子
*求字符串长度——strlen()
关于**strlen()**我们需要知道几个点:
size_t strlen ( const char * str );//返回无符号整型
- 字符串已经 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包 含 ‘\0’ )。
- 参数指向的字符串必须要以 ‘\0’ 结束。
- 注意函数的返回值为size_t,是无符号的( 易错 )
- 学会strlen函数的模拟实现
对于第3点我们怎么去理解我们可以来举个例子:
#include <stdio.h>
#include <string.h>
int main()
{
//返回无符号整型
if (strlen("abc") - strlen("abcdef") > 0)
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
输出结果是什么
是:>
因为strlen()返回无符号整型,虽然3-6<0,但是对于无符号的数来说,怎么可能有负数呢?所以结果肯定是>号
我们可以来测试运行一下结果:
本篇博客主要的内容就是函数的模拟实现
下面我们介绍strlen()的三种模拟实现方法:
1.计数器方法
直接定义一个变量去统计字符串的长度:
#include <stdio.h>
#include <string.h>
#include <assert.h>
//计数器方法
size_t my_strlen(const char*str)
{
int count = 0;
assert(str);
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "abcdef";
size_t n = my_strlen(arr);
printf("%u\n", n);
return 0;
}
同时,我们需要严谨一些,注意一些细节:
- 第一个就是const修饰,我们只需要去访问,不需要进行修改操作
- 第二个就是assert断言,如果传过来的是空的呢?这就是assert的用处了
- 第三个就是返回值size_t无符号
2.指针-指针方法
#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
assert(str);
char* ret = str;
while (*str != '\0')
{
str++;
}
return str - ret;
}
int main()
{
char arr[] = "abcdef";
size_t n = my_strlen(arr);
printf("%u\n", n);
return 0;
}
指针减去指针就是元素的个数,所以我们记录刚开始的地址,由最后一个指针地址减去刚开始记录的指针地址就可以得到长度了!
3.递归
找出递归条件可以完美模拟实现strlen()。下面进行代码实现:
#include <stdio.h>
#include <string.h>
#include <assert.h>
size_t my_strlen(const char* str)
{
assert(str);
if (*str == '\0')
{
return 0;
}
return 1 + my_strlen(str + 1);
}
int main()
{
char arr[] = "abcdef";
size_t n = my_strlen(arr);
printf("%u\n", n);
return 0;
}
测试运行:
*长度不受限制的字符串函数
strcpy
对于strcpy(),我们要知道几个点:
char* strcpy(char * destination, const char * source );
- Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point). 简单理解就是字符串的拷贝,不过拷贝要注意下面几个点:
- 源字符串必须以 ‘\0’ 结束。
- 会将源字符串中的 ‘\0’ 拷贝到目标空间。
- 目标空间必须足够大,以确保能存放源字符串。
- 目标空间必须可变。 学会模拟实现。
我觉得这个函数最重要的一点是:第一个参数是目的地字符串,第二个参数是源来的字符串。第二个参数是不可改变的,可以用const来修饰。这点比较重要。
下面我们来对其进行模拟实现:
//模拟实现
#include <stdio.h>
char* my_strcpy(char* dest, const char* src)
{
assert(dest);
assert(src);
char* ret = dest;
while (*src)
{
*dest++ = *src++;
}
*dest = *src;
return ret;
}
int main()
{
char arr1[] = "abcdef";
char arr2[20] = {
0 };
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
对于这次的模拟实现我们可以进行优化,使之看起来更加简化
#include <stdio.h>
char* my_strcpy(char* dest, char* src)
{
assert(dest && src);
char* ret = dest;
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[] = "abcdef";
char arr2[20] = {
0 };
my_strcpy(arr2, arr1);
printf("%s\n", arr2);
return 0;
}
测试运行结果:
strcat
char * strcat ( char * destination, const char * source );
- Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source, and a null-character is included at the end of the new string formed by the concatenation of both in destination. 简单理解,就是字符串的追加。
- 源字符串必须以 ‘\0’ 结束。
- 目标空间必须有足够的大,能容纳下源字符串的内容。
- 目标空间必须可修改。 字符串自己给自己追加,如何?
有了上面的知识点之后,对于strcat我们是很好理解的,下面我们先来进行模拟实现:
#include <stdio.h>
//字符串追加
//字符串追加
char* my_strcat(char* dest, const char* src)
{
assert(dest && src);
int ret = dest;
while (*dest != '\0')
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "hello ";
strcat(arr1, "world");
//my_strcat(arr1, "world");
//自己给自己追加?
//my_strcat(arr1, arr1);//这是错误的,破坏了本身自己。\0不见了
printf("%s\n", arr1);
return 0;
}
测试运行:
这里有人会问了:自己给自己追加呢?想想看,这是错误的做法,因为你会发现,追加自己的过程中本身自己发生了变化,'\0’被覆盖了,根本无法实现。无论是我们自己模拟实现的或者库函数自己的,都没法自己追加自己。
strcmp
int strcmp ( const char * str1, const char * str2 );
- This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached. 简单来说,就是进行字符串的比较。
- 标准规定: 第一个字符串大于第二个字符串,则返回大于0的数字
- 第一个字符串等于第二个字符串,则返回0
- 第一个字符串小于第二个字符串,则返回小于0的数字
- 那么如何判断两个字符串?比较的是对应的ASCII码值
先来简单理解一下库函数把:
#include <stdio.h>
int main()
{
int ret = strcmp("abbb", "abq");
printf("%d", ret);
return 0;
}
将会得到:
因为第三位b小于q的ASCII码值,自然返回-1。这就是strcmp的基本原理。
不过这里我们要对其进行模拟实现,怎么模拟实现呢
#include <stdio.h>
int my_strcmp(const char* s1, const char* s2)
{
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
if (*s1 > *s2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char* p = "abcdef";
char* q = "abbb";
int ret = my_strcmp(p, q);
if (ret>0)
{
printf("p>q");
}
else if(ret <0)
{
printf("p<q");
}
else
{
printf("p=q");
}
return 0;
}
测试运行结果:
这样就完了吗?并没有,我们可以对模拟实现的代码进行优化简洁一些:
//优化模拟实现
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* s1, const char* s2)
{
assert(s1 && s2);
while (*s1 == *s2)
{
if (*s1 == '\0')
{
return 0;
}
s1++;
s2++;
}
return *s1 - *s2;
}
int main()
{
char* p = "abcdef";
char* q = "abbb";
int ret = my_strcmp(p, q);
if (ret>0)
{
printf("p>q");
}
else if(ret <0)
{
printf("p<q");
}
else
{
printf("p=q");
}
return 0;
}
注意到:
并没有具体要求<0的数是多少,或者说>0的数是多少,我们直接去相减即可。
测试运行一下代码:
*总结
关于求字符串长度以及长度不受限制的字符串函数的相关介绍及其模拟实现就到这里结束了,然后考虑到实际情况,我们一次性如果学太多库函数的话反而不利于形成记忆,对函数不能熟练的掌握,本篇博客就先介绍这4个函数的实现,其余的留在下次!
同时记得自己多总结一下,多动手去敲代码,不要自己认为看得懂就会了,实际操作起来是跟自己的想法是不一样的,希望大家能够多动手去实践一下!
边栏推荐
- golang通过指针for...range实现切片中元素的值的更改
- How to choose the notion productivity tools? Comparison and evaluation of notion, flowus and WOLAI
- 软件测试是干什么的?学习有啥要求?
- shell编程基础(第9篇:循环)
- Decision tree and random forest
- JMeter 常用的几种断言方法,你会了吗?
- Tianyi cloud understands enterprise level data security in this way
- Fundamentals of machine learning (III) -- KNN / naive Bayes / cross validation / grid search
- 潘多拉 IOT 开发板学习(HAL 库)—— 实验8 定时器中断实验(学习笔记)
- Golang through pointer for Range implements the change of the value of the element in the slice
猜你喜欢
Postman核心功能解析-参数化和测试报告
cf:B. Almost Ternary Matrix【对称 + 找规律 + 构造 + 我是构造垃圾】
面试官:Redis中集合数据类型的内部实现方式是什么?
Cf:b. almost Terry matrix [symmetry + finding rules + structure + I am structural garbage]
The road of enterprise digital transformation starts from here
为什么 BI 软件都搞不定关联分析?带你分析分析
Android interview, Android audio and video development
2022 the most complete Tencent background automation testing and continuous deployment practice in the whole network [10000 words]
Advanced application of C # language
关于 Notion-Like 工具的反思和畅想
随机推荐
Mathematical modeling of oil pipeline layout MATLAB, mathematical model of oil pipeline layout
flume系列之:拦截器过滤数据
Fuzor 2020軟件安裝包下載及安裝教程
Ultrasonic ranging based on FPGA
手把手教你处理 JS 逆向之图片伪装
CF: B. almost Ternary Matrix [symétrie + règles de recherche + Construction + I am Construction Waste]
Go语言 | 01 WSL+VSCode环境搭建避坑指南
R language Visual scatter plot graph, add labels to some data points in the graph, and always display all labels, even if they have too much overlap. Ggrep package helps
决策树与随机森林
R语言使用lubridate包处理日期和时间数据实战
HAC cluster modifying administrator user password
如何在2022年更明智地应用智能合约?
Startup and shutdown of CDB instances
UDF implementation of Dameng database
golang通过指针for...range实现切片中元素的值的更改
Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
Pandora IOT development board learning (HAL Library) - Experiment 8 timer interrupt experiment (learning notes)
Android面试,android音视频开发
公司破产后,黑石们来了
PHP利用ueditor实现上传图片添加水印