🎈个人主页:🎈 :✨✨✨初阶牛✨✨✨ 🐻推荐专栏: 🍔🍟🌯 c语言进阶 🔑个人信条: 🌵知行合一 🍉本篇简介:>:介绍c语言中有关字符函数与字符串函数部分库函数.包括模拟实现,参数介绍等. 金句分享: ✨没有一朵花从一开始就是一朵花.✨
学习库函数的模拟实现之前,要先了解两个这两个
const关键字和assert()库函数
1.对于**const关键字,**这位博主讲的十分详细. const介绍 2.assert函数简单介绍. 函数名:断言函数 头文件:
#include <assert.h>
作用: 判断参数表达式的真假,如果为假就会终止程序,打印错误信息. 对于程序员这是一个非常友好的函数,可以减少出错的可能性,由于会返回错误到具体的哪一行,也就省去了调试的成本. assert()中的参数表达式为真时,什么也不会发生,在release版本中,assert会被优化掉.
推荐查询库函数的网站: 查询库函数的网站
函数原型:
用于计算字符串的长度.(输入字符串首地址,返回字符串长度).
头文件
#include <string.h>
参数 | 意义 |
---|---|
const char * str | 要计算长度的字符串的首地址 |
返回值: 该字符串’\0’之前的字符个数,即不包括’\0’.
函数应用
#include <stdio.h>
#include <string.h>
int main()
{
char arr[100]={0};
printf("请输入字符串:\n");
scanf("%s", arr);//这里可以不用&arr,因为arr是数组名,是数组的首地址
size_t ret = strlen(arr);
printf("字符串长度%zd", ret);
return 0;
}
//模拟实现strlen
#include <stdio.h>
#include <assert.h>
size_t my_strlen1(const char* str)//方法一:计数法
{
assert(str);
int count = 0;
while (*str++)
{
count++;
}
return count;
}
size_t my_strlen2(const char* str)//方法二:递归方式实现
{
assert(str);
if (*str != '\0')
{
return 1 + my_strlen2(str + 1);
}
return 0;
}
size_t my_strlen3(const char* str)//方法三:指针-指针
{
assert(str);
char* ret = str;
while (*ret)
{
ret++;
}
return ret - str;
}
int main()
{
char arr[] = { "abcdefg" };
printf("%d\n", my_strlen1(arr));
printf("%d\n", my_strlen2(arr));
printf("%d\n", my_strlen3(arr));
return 0;
}
要保证被计算的字符串中包含’\0’,如果字符串没有包含’\0’,就会接续往后寻找,直到遇到’\0’,即产生随机值.
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = { 'a','b','c' };
int ret = strlen(arr);
printf("%d", arr);
return 0;
}
运行结果:
随机值
小细节: 你知道size_t是什么吗?
你知道这段代码的运行结果是什么吗?
#include <stdio.h>
#include <string.h>
int main()
{
if (strlen("abc") - strlen("abcdef"))
{
printf("大于");
}
else
{
printf("小于等于");
}
return 0;
}
运行结果:
大于
原因就是size_t 3-6虽然结果是-3,但是对于无符号整形来说,就是一个很大的正数了.
其实size_t的本质是无符号整形,毕竟一个字符串的长度是非负数,所以库函数的设计还是比较合理的.
typedef unsigned int size_t;
函数模型
用于将源地址的字符串拷贝到目的地址.
函数名:字符串拷贝函数
头文件:
#include <string.h>
参数 | 意义 |
---|---|
参数1:char * destination | 目的地址: 指向要在其中复制内容的目标数组的指针。 |
参数2:const char * source | 源地址:要复制的 C 字符串。 |
返回值:拷贝完成后目的地址.
🌰栗子
#include<stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "xxxxxxxxxxxxxxx" ;
char arr2[] = "hello csdn" ;
printf("%s", strcpy(arr1, arr2));
return 0;
}
运行结果:
hello csdn
为了更加方便的观察拷贝的结果,我们可以通过调试,在监视窗口观察arr1的存放结果.
很明显,strcpy函数是从源地址的首地址处开始,直到遇到’\0’,最后将’\0’也拷贝过去. 为了验证是否真的只是到’\0’而不是所有数据. 将代码改成:
#include<stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "xxxxxxxxxxxxxxx" ;
char arr2[] = "hello\0 csdn" ;
printf("%s", strcpy(arr1, arr2));
return 0;
}
验证结果是正确的.
#include <stdio.h>
//destination目的地 source源地址
char* my_strcpy1(char* dest, char* src)//第一种
{
char* ret = dest;//记录首地址
while (*src != '\0')
{
*dest = *src;
dest++;
src++;
}
*dest++ = *src++;
return ret;
}
char* my_strcpy2(char* dest, char* src)//优化1,代码变得更加简洁
{
char* ret = dest;
while (*dest++=*src++)
{
;
}
return ret;
}
#include <assert.h>
char* my_strcpy3(char* dest, const char* src)
{
assert(dest && src);//防止传入空指针
char* ret = dest;
while (*dest++ = *src++)//刚好最后将'\0'覆盖过去
{
;
}
return ret;
}
int main()
{
char arr1[] = { "HELLO CSDN!" };
char arr2[20] = { "xxxxxxxxxxxxxxxxxx" };
char* p = NULL;//空指针
printf("%s\n", my_strcpy1(arr2, arr1));
//printf("%s\n", my_strcpy2(arr2, arr1));
//printf("%s\n", my_strcpy3(arr2, arr1));
return 0;
}
函数模型:
将源字符串(source)的副本(复制一份)追加到目标字符串(destination)。目标中的终止空字符(‘\0’)被源字符串的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符(‘\0’)。
参数 | 意义 |
---|---|
参数1:char * destination | 目的地址: 指向要在后面追加字符串的目标数组的指针。 |
参数2:const char * source | 源地址:要追加的 C 字符串。 |
函数应用:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "HELLO ";
char arr2[] = "CSDN!";
strcat(arr1,arr2);
printf("%s", arr1);
return 0;
运行结果:
HELLO CSDN!
#include <stdio.h>
#include <assert.h>
my_strcat(char* dest, const char* src)
{
assert(dest && src);//防止传入空指针
char* ret = dest;
while (*dest)
{
dest++;
}
while (*dest++ = *src++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "HELLO ";
char arr2[] = "CSDN!";
my_strcat(arr1,arr2);
printf("%s", arr1);
return 0;
}
函数模型:
头文件:
#include <stdio.h>
将 C 字符串 str1 与 C 字符串 str2 进行比较。 此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续向后比较,直到字符不同或达到终止空字符。 返回值: 返回一个整数值,该值指示字符串之间的关系
返回值 | 意义 |
---|---|
<0 | 第一个不匹配的字符的str1的值小于str2中的值 |
0 | 两个字符串的内容相等 |
>0 | 第一个不匹配的字符的str1的值大于于str2中的值 |
参数 | 意义 |
---|---|
参数1:const char * str1 | 指向字符串1的指针 |
参数2 const char * str2 | 指向字符串2的指针 |
函数应用: 实现一个设置密码,只有三次机会.
#define MAX 3
#include <stdio.h>
#include <string.h>
int main()
{
char password[] = "1433223";
char input[20];
for (int i = MAX; i > 0; i--)
{
printf("请输入密码:\n你还有%d次机会:\n", i);
scanf("%s", input);
if (password== input)
{
printf("恭喜你,密码正确!!!");
break;
}
else
{
printf("很遗憾,密码错误\n");
}
}
return 0;
}
运行结果:
请输入密码: 你还有3次机会: 123 很遗憾,密码错误 请输入密码: 你还有2次机会: 1433223 很遗憾,密码错误 请输入密码: 你还有1次机会: 1234 很遗憾,密码错误
当密码输入正确时,也显示密码错误,因为字符串不能直接用"=="进行比较,而要借助库函数,strcmp函数进行比较.
#define MAX 3
#include <stdio.h>
#include <string.h>
int main()
{
char password[] = "1433223";
char input[20];
for (int i = MAX; i>0; i--)
{
printf("请输入密码:\n你还有%d次机会:\n",i);
scanf("%s", input);
if (strcmp(password,input)==0)
{
printf("恭喜你,密码正确!!!");
break;
}
else
{
printf("很遗憾,密码错误\n");
}
}
return 0;
}
运行结果:
请输入密码: 你还有3次机会: 123 很遗憾,密码错误 请输入密码: 你还有2次机会: 123456 很遗憾,密码错误 请输入密码: 你还有1次机会: 1433223 恭喜你,密码正确!!!
int my_strcmp(const char* str1, const char* str2)
{
assert(str1 && str2);
while (*str1 == *str2)
{
if (*str2 == '\0')//循环条件是,字符串的元素相等,如果一方是'\0',说明两者都是'\0'.
{
return 0;//返回0,说明两者相等
}
str1++;
str2++;
}
//跳出循环,说明有字符元素不相等
if (*str1 > *str2)//比较哪方的字符更大
{
return 1;
}
else
{
return -1;
}
}
注意事项: 此函数执行字符的二进制比较,实际比较的是字符的ASCII码值,并不是按长度比较. 而是比较第一次出现不同字符的大小. 在vs编译器下,
第一个字符串大于第二个字符串,返回1; 相等返回0 第一个字符串小于第二个字符串,返回-1; 而与库函数本身有点小的差别,库函数要求返回>0 0和<0的数即可.
后续会更新strncpy,strncat,strncmp,strstr,strtok,strerror=等库函数讲解. 今天就先到这里啦!!! 886