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

简介: 库函数之字符函数与字符串函数(上)

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


const关键字和assert()库函数


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


const介绍


2.assert函数简单介绍.


函数名:断言函数


头文件:


#include <assert.h>


作用:


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


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


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


推荐查询库函数的网站:


查询库函数的网站



一、strlen函数


函数原型:



函数作用:


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


头文件


#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;


二、strcpy函数


函数模型



函数作用:


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


函数名:字符串拷贝函数


头文件:


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


注意事项:


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


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


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


三、strcat函数


函数模型:



函数作用:


将源字符串(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;
}


注意事项:


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


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


  • 目标空间必须可修改。


重点


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


四、strcmp函数


函数模型:



头文件:


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


目录
相关文章
|
C语言
【c语言】字符函数与字符串函数(上)
【c语言】字符函数与字符串函数(上)
60 0
|
7月前
|
安全 Serverless C语言
C语言(10)----字符函数和字符串函数
C语言(10)----字符函数和字符串函数
34 0
|
7月前
|
安全 编译器 程序员
C语言之字符函数&字符串函数篇(1)
C语言之字符函数&字符串函数篇(1)
71 0
|
7月前
|
存储 C语言
C语言:字符函数和字符串函数
C语言:字符函数和字符串函数
|
7月前
|
C语言
字符函数和字符串函数
字符函数和字符串函数
78 0
|
7月前
|
C语言
C语言 - 字符函数和字符串函数
C语言 - 字符函数和字符串函数
|
C语言 Python
字符函数和字符串函数(下)
字符函数和字符串函数(下)
58 0
字符函数和字符串函数(下)
|
C语言 C++
C语言之字符函数&字符串函数篇(2)
C语言之字符函数&字符串函数篇(2)
80 0