关于我们

质量为本、客户为根、勇于拼搏、务实创新

< 返回新闻公共列表

库函数之字符函数与字符串函数(上)

发布时间:2023-06-27 00:00:34

学习库函数的模拟实现之前,要先了解两个这两个


const关键字和assert()库函数


1.对于const关键字,这位博主讲的十分详细.


const介绍


2.assert函数简单介绍.


函数名:断言函数


头文件:


#include

   


作用:


判断参数表达式的真假,如果为假就会终止程序,打印错误信息.


对于程序员这是一个非常友好的函数,可以减少出错的可能性,由于会返回错误到具体的哪一行,也就省去了调试的成本.


assert()中的参数表达式为真时,什么也不会发生,在release版本中,assert会被优化掉.


推荐查询库函数的网站:


查询库函数的网站



一、strlen函数


函数原型:



函数作用:


用于计算字符串的长度.(输入字符串首地址,返回字符串长度).


头文件


#include

   


函数参数:


参数意义
const char * str要计算长度的字符串的首地址


返回值:


该字符串’\0’之前的字符个数,即不包括’\0’.


函数应用


#include#includeint main() {  char arr[100]={0};  printf("请输入字符串:\n");  scanf("%s", arr);//这里可以不用&arr,因为arr是数组名,是数组的首地址  size_t ret = strlen(arr);  printf("字符串长度%zd", ret);  return 0; }

   


模拟实现:


//模拟实现strlen #include#includesize_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#includeint main() {  char arr[] = { 'a','b','c' };  int ret = strlen(arr);  printf("%d", arr);  return 0; }

   


运行结果:


随机值


小细节:


你知道size_t是什么吗?


你知道这段代码的运行结果是什么吗?


#include#includeint main() {  if (strlen("abc") - strlen("abcdef"))  {  printf("大于");  }  else  {  printf("小于等于");  }  return 0; }

   


运行结果:


大于


原因就是size_t


3-6虽然结果是-3,但是对于无符号整形来说,就是一个很大的正数了.


其实size_t的本质是无符号整形,毕竟一个字符串的长度是非负数,所以库函数的设计还是比较合理的.


typedef unsigned int size_t;

   


二、strcpy函数


函数模型



函数作用:


用于将源地址的字符串拷贝到目的地址.


函数名:字符串拷贝函数


头文件:


#include

   


函数参数:


参数意义
参数1:char * destination目的地址: 指向要在其中复制内容的目标数组的指针。
参数2:const char * source源地址:要复制的 C 字符串。


返回值:拷贝完成后目的地址.


栗子


#include#includeint main() {  char arr1[20] = "xxxxxxxxxxxxxxx" ;  char arr2[] = "hello csdn" ;  printf("%s", strcpy(arr1, arr2));  return 0; }

   


运行结果:


hello csdn


为了更加方便的观察拷贝的结果,我们可以通过调试,在监视窗口观察arr1的存放结果.



很明显,strcpy函数是从源地址的首地址处开始,直到遇到’\0’,最后将’\0’也拷贝过去.

为了验证是否真的只是到’\0’而不是所有数据.


将代码改成:


#include#includeint main() {  char arr1[20] = "xxxxxxxxxxxxxxx" ;  char arr2[] = "hello\0 csdn" ;  printf("%s", strcpy(arr1, arr2));  return 0; }

   


 


验证结果是正确的.


模拟实现:


#include//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; }  #includechar* 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; }

   


注意事项:


  • 源字符串必须以 ‘\0’ 结束。


  • 会将源字符串中的 ‘\0’ 拷贝到目标空间。


  • 目标空间必须足够大,以确保能存放源字符串


三、strcat函数


函数模型:



函数作用:


将源字符串(source)的副本(复制一份)追加到目标字符串(destination)。目标中的终止空字符(‘\0’)被源字符串的第一个字符覆盖,并且在目标中由两者串联形成的新字符串的末尾包含一个空字符(‘\0’)。



函数参数


参数意义
参数1:char * destination目的地址: 指向要在后面追加字符串的目标数组的指针。
参数2:const char * source源地址:要追加的 C 字符串。


函数应用:


#include#includeint main() {  char arr1[20] = "HELLO ";  char arr2[] = "CSDN!";  strcat(arr1,arr2);  printf("%s", arr1);  return 0;

   


运行结果:


HELLO CSDN!


模拟实现:


 #include#includemy_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; }

   


注意事项:


  • 源字符串必须以 ‘\0’ 结束。


  • 目标空间必须有足够的大,能容纳下源字符串的内容。


  • 目标空间必须可修改。


重点


  • 不可自己追加自己,否则不知道什么时候停下来,因为’\0’被改掉了.


四、strcmp函数


函数模型:



头文件:


#include

   


函数作用:


将 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#includeint 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#includeint 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的数即可.



/template/Home/leiyu/PC/Static