✨作者:@平凡的人1
✨专栏:《C语言从0到1》
✨一句话:凡是过往,皆为序章
✨说明: 过去无可挽回, 未来可以改变
我们知道,在C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的(不像其他语言直接String即可解决),在C语言中字符串通常放在常量字符串中或者字符数组中。
字符串常量适用于那些对它不做修改的字符串函数。
我们这次主要介绍的就是一些字符串函数。
- 关于学习一些陌生的函数:我们可以通过cplusplus.com进行了解学习,知道参数所代表的含义以及实现的功能是上面,这可以让我们事半功倍!对于英文不理解的话,我们可以翻译成自己熟悉的中文啦。
- 一定要自己多动手去实现代码哦,也不要一口气吃成胖子
关于**strlen()**我们需要知道几个点:
size_t strlen ( const char * str );//返回无符号整型
对于第3点我们怎么去理解❓我们可以来举个例子:
#include
#include
int main()
{
//返回无符号整型
if (strlen("abc") - strlen("abcdef") > 0)
{
printf(">\n");
}
else
{
printf("<\n");
}
return 0;
}
输出结果是什么❓
是:>
因为strlen()返回无符号整型,虽然3-6<0,但是对于无符号的数来说,怎么可能有负数呢?所以结果肯定是>号
我们可以来测试运行一下结果:
下面我们介绍strlen()的三种模拟实现方法:
直接定义一个变量去统计字符串的长度:
#include
#include
#include
//计数器方法
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;
}
同时,我们需要严谨一些,注意一些细节:
#include
#include
#include
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;
}
指针减去指针就是元素的个数,所以我们记录刚开始的地址,由最后一个指针地址减去刚开始记录的指针地址就可以得到长度了!
找出递归条件可以完美模拟实现strlen()。下面进行代码实现:
#include
#include
#include
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(),我们要知道几个点:
char* strcpy(char * destination, const char * source );
我觉得这个函数最重要的一点是:第一个参数是目的地字符串,第二个参数是源来的字符串。第二个参数是不可改变的,可以用const来修饰。这点比较重要。
下面我们来对其进行模拟实现:
//模拟实现
#include
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
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;
}
char * strcat ( char * destination, const char * source );
有了上面的知识点之后,对于strcat我们是很好理解的,下面我们先来进行模拟实现:
#include
//字符串追加
//字符串追加
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’被覆盖了,根本无法实现。无论是我们自己模拟实现的或者库函数自己的,都没法自己追加自己。
int strcmp ( const char * str1, const char * str2 );
先来简单理解一下库函数把:
#include
int main()
{
int ret = strcmp("abbb", "abq");
printf("%d", ret);
return 0;
}
因为第三位b小于q的ASCII码值,自然返回-1。这就是strcmp的基本原理。
不过这里我们要对其进行模拟实现,怎么模拟实现呢❓
#include
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);
}
else
{
printf("p=q");
}
return 0;
}
这样就完了吗?并没有,我们可以对模拟实现的代码进行优化简洁一些:
//优化模拟实现
#include
#include
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);
}
else
{
printf("p=q");
}
return 0;
}
并没有具体要求<0的数是多少,或者说>0的数是多少,我们直接去相减即可。
关于求字符串长度以及长度不受限制的字符串函数的相关介绍及其模拟实现就到这里结束了,然后考虑到实际情况,我们一次性如果学太多库函数的话反而不利于形成记忆,对函数不能熟练的掌握,本篇博客就先介绍这4个函数的实现,其余的留在下次!
同时记得自己多总结一下,多动手去敲代码,不要自己认为看得懂就会了,实际操作起来是跟自己的想法是不一样的,希望大家能够多动手去实践一下!