【C语言进阶】字符串函数与内存函数的学习与模拟实现(上)

简介: 【C语言进阶】字符串函数与内存函数的学习与模拟实现(上)

1.字符串处理函数介绍

我们在C语言的从程序代码编写中,对字符和字符串的处理相当频繁,但是C语言本身并没有字符串类型。而字符串通常放在【常量字符串】或者【字符数组】中。其中,字符串常量适用于那些对它不做修改的字符串函数。

1.1 strlen 函数:

strlen 函数(string length)的作用是计算返回字符串中结束标识符 ’ \0 ’ 之前出现的的字符个数,因此,strlen函数所处理的字符串必须是以结束标识符 ’ \0 ’ 结尾的字符串。其·返回值类型为size_t 类型,该类型为无符号类型。

strlen 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
    //两中可行的初始化方式:
  char arr1[]="Hello!";
  char arr2[] = { 'H','e','l','l','o','!','\0' };
  int ret1 = strlen(arr1);
  int ret2 = strlen(arr2);
  printf("The length of arr1 is %d\n", ret1);
  printf("The length of arr2 is %d\n", ret2);
  return 0;
}

944ac19f322e4208867e77862f6501ca.png

我们使用字符型数组将字符串储存起来,接着使用 strlen 函数计算字符串 " Hello! " 中所有字符的数量使用双引号初始化字符串时,编译器将会自动在最后添加上结束标识符,并可以使用一个整型变量接收 strlen 函数的返回值,进行打印。

并且我们还说到,strlen 函数的返回类型为无符号数,因此 strlen 函数不可以直接用来比较两个字符串的大小。例如:

#include<stdio.h>
#include<string.h>
int main()
{
  const char* str1 = "abcdef";
  const char* str2 = "bbb";
if (strlen(str2) - strlen(str1) > 0)
  {
    printf("str2 > str1\n");
  }
  else
  {
    printf("srt1 < str2\n");
  }
  return 0;
}

我们可能会认为计算出的结果为 3 - 6 为 -3,结果会执行 else 语句。但事实上,因为 strlen 函数的返回类型为无符号类型,得出的结果也是无符号类型,于是原本第一位即符号位上的数字也将被作为数据的一部分,因而实际得出的结果为一个非常大的整数,执行了 if 语句。

于是如果我们想要使用 strlen 函数来判断字符串的大小,可以通过让它的返回值由无符号数变为有符号数即可,即强制类型转换来实现:

#include<stdio.h>
#include<string.h> 
int main()
{
  const char* str1 = "abcdef";
  const char* str2 = "bbb";
if ((int)strlen(str2) - (int)strlen(str1) > 0)
  {
    printf("str2 > str1\n");
  }
  else
  {
    printf("srt1 < str2\n");
  }
  return 0;
}

1.2 strcpy 函数:

在之前的学习中,strcpy 函数也是我们经常使用的字符串处理函数之一。strcpy 函数(string copy)的作用是,可以将字符串从源地址复制至目的地址并且它会将源地址内的结束标识符 ’ \0 ’ 一并拷贝过去,因此源地址必须以 ’ \0 ’ 结尾,且目的地址也将以结束标识符结尾,通俗来讲就是用来实现字符串的复制和拷贝。并且,因为其作用为拷贝字符串,因此目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可变、可修改的。

strcpy 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[] = "Hellow!";
  const char arr2[10] = { 0 };
  printf("Before copy , the char inside arr1 are %s\n", arr1);
  printf("Before copy , the char inside arr2 are %s\n", arr2);
  printf("\n");
  strcpy(arr2, arr1);
    //strcpy函数使用格式为:strcpy(目的地址, 源地址)
  printf("After copy , the char inside arr1 are %s\n", arr1);
  printf("After copy , the char inside arr2 are %s\n", arr2);
  return 0;
}

2e0bb72ef709478eb43f383e25ce6a16.png

我们要特别注意的是 strcpy 函数返回的是目标空间的起始地址,该函数设置返回值值类型的目的是为了实现链式访问

1.3 strcat 函数:

strcat 函数(string catenate)的作用是,将源地址的字符串追加补充至目的地址处。与字符串拷贝函数相同,它在进行补充追加时是从目的地址的结束标识符处 ’ \0 ’ 开始追加的追加至源地址的结束标识符处停止。且它同样要求目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可变、可修改的。

strcat 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[20] = "Hello!";
  const char arr2[20] = "Welcome!";
  printf("Before catenate , the char inside arr1 are %s\n", arr1);
  printf("Before catenate , the char inside arr2 are %s\n", arr2);
  printf("\n");
  strcat(arr2, arr1);
  printf("After catenate , the char inside arr1 are %s\n", arr1);
  printf("After catenate , the char inside arr2 are %s\n", arr2);
  return 0;
}

48b34d6cb9d44004bce8920ea6eec27c.png注意 strcat 函数无法追加自己。原因很好理解,我们在定义时就已经固定了字符数组的储存空间了,当追加自己时,相当于将自己与和与自己相同大小的字符数组,即两倍自身大小的数据放入自己的储存空间中,可想而知一定是不可行的。

1.4 strcmp 函数:

strcmp 函数(string compare)的作用为按照顺序依次比较两字符串对应位置字符的 ASCII 码值(注意不是比较两字符串的长度),直到结束标识符 ’ \0 ’ 或对应位置的字符不同若比较至结束标识符都没有不同则两字符串相等,若两字符串对应位置字符有不同,对应位置上字符 ASCII 码值小的字符串小于另一个字符串。

我们来看 strcmp 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[] = "abcd";
  const char arr2[] = "abz";
  int ret = strcmp(arr1, arr2);
  //若arr1大于arr2,则返回大于零的数
  //若arr1等于arr2,则返回等于零的数
  //若arr1小于arr2,则返回小于零的数
  if (ret > 0)
  {
    printf("arr1 > arr2\n");
  }
  else if (ret = 0)
  {
    printf("arr1 = arr2\n");
  }
  else
  {
    printf("arr1 < arr2\n");
  }
  return 0;
}

c1388d2932e54168ab913cf113740b92.png定义并初始化两个字符数组,接着对两个数组进行比较,根据 strcmp 函数的比较结果得到返回值,再根据返回值反馈我们想要的字符串比较结果。

注意并不是比较字符串的长短,而是比较对应位置字符 ASCII 码值的大小

1.5 strncpy 函数:

strncpy函数(string number copy)的作用为将指定长度的字符串复制到字符数组中,即表示把源地址中字符串开始的前n个字符拷贝到目的地址中。与 strcpy 相同,它同样会将源地址内的结束标识符 ’ \0 ’ 一并拷贝过去,因此源地址必须以 ’ \0 ’ 结尾,且目的地址也将以结束标识符结尾。并且,因为其作用为拷贝字符串,因此目标地址内的空间必须足够大,要有足够的空间容纳下源地址内的字符串,同时目的地址的空间必须是可变、可修改的。

strncpy 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
 //strncpy函数的使用:
int main()
{
  const char arr1[] = "Hellow!Welcome!";
  const char arr2[10] = { 0 };
  printf("Before copy , the char inside arr1 are %s\n", arr1);
  printf("Before copy , the char inside arr2 are %s\n", arr2);
  strncpy(arr2, arr1, 7);
  printf("After catenate , the char inside arr1 are %s\n", arr1);
  printf("After catenate , the char inside arr2 are %s\n", arr2);
 return 0;
}

e0df74ce132141d5900688cae1794f90.png我们看到,使用该函数,我们成功的将字符数组 arr1 中的前七个字符拷贝到了字符数组 arr2 中。

注意:若源字符串的长度小于我们传递过去的参数,则拷贝完源字符串之后,将会在目标后追加字符 ’ 0 ',直到拷贝至参数规定个数。

1.6 strncat 函数:

strncat 函数(string num catenate)的作用为从源地址处将指定长度的字符串追加补充到目的地址中与 strcat 函数类似,它在进行补充追加时也是从目的地址的结束标识符处 ’ \0 ’ 开始追加的,不同的是追加至参数限制的字符数处停止。但它同样要求目标地址内的空间必须足够大,要有足够的空间容纳下出家补充的字符串 ,同时目的地址的空间必须是可变、可修改的。

strncat 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[] = "Hellow!Welcome!";
  const char arr2[20] = "Welcome!";
  printf("Before copy , the char inside arr1 are %s\n", arr1);
  printf("Before copy , the char inside arr2 are %s\n", arr2);
  strncat(arr2, arr1, 7);
  printf("After catenate , the char inside arr1 are %s\n", arr1);
  printf("After catenate , the char inside arr2 are %s\n", arr2);
  return 0;
}

d753b58f68394c63bc72388a60f8832e.png我们可以看到,首先定义并初始化两个字符数组,接着打印追加补充之前它们各自空间内的内容进行确认,然后我们使用了 strncat 函数有限制的从数组 arr1 向 arr2 中追加补充了七个字符。

通过限制长度我们就可以实现字符数组对自己的追加补充了。

1.7 strncmp 函数:

strncmp 函数(string number compare)的作用为有限制的按照顺序依次比较两字符串对应位置字符的 ASCII 码值(注意不是比较两字符串的长度),直到参数限制位数位置上全部比较结束或对应位置的字符不同。若参数限制位数位置上的字符都比较结束且都没有不同则两字符串相等,若两字符串对应位置字符有不同,对应位置上字符 ASCII 码值小的字符串小于另一个字符串。

strncmp 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[] = "abcd";
  const char arr2[] = "abz";
  int ret = strncmp(arr1, arr2, 3);
    //比较前 3 个字符
  //若arr1大于arr2,则返回大于零的数
  //若arr1等于arr2,则返回等于零的数
  //若arr1小于arr2,则返回小于零的数
 if (ret > 0)
  {
    printf("arr1 > arr2\n");
  }
  else if (ret = 0)
  {
    printf("arr1 = arr2\n");
  }
  else
  {
    printf("arr1 < arr2\n");
  }
 return 0;
}

5575635cb28a4ea9b4e75fe90323b570.png其作用原理与作用过程,与 strncmp 函数十分类似,唯一不同便是限制了字符比较的位数

注意该函数的作用也不是比较字符串的长短,而是比较对应位置字符 ASCII 码值的大小

1.8 strstr 函数:

strstr 函数(string string)的作用为从一个字符串中寻找其字串,通俗来讲就是从一个字符串中寻找另一个字符串若找到目标字串则返回指向目标字串的指针,若没有找到目标字串则返回空指针(不返回)

strstr 函数的基本使用方式:

#include<stdio.h>
#include<string.h>
int main()
{
  const char arr1[] = "abcdefg";
  const char arr2[] = "cde";
 char* ret = strstr(arr1, arr2);
  //从ar1中寻找arr2
  if (ret == NULL)
  {
    printf("找不到该字符串!\n");
  }
  else
  {
    printf("成功找到该字符串'%s'!\n", ret);
  }
 return 0;
}

819552777e494a11ba9ddfa13cf73689.png我们定义并初始化了两个字符数组,并使用 strstr 函数进行字串寻找处理,并使用字符型指针接收汉函数的返回值,最后,对接收了返回值的指针 ret 进行判断,若为空则确定为没有从数组 arr1 中找到字串 arr2,否则便通过返回值,使用指针对字串地址内的数据进行访问。

该函数数有返回值,支持进行函数的链式访问


相关文章
|
6天前
|
程序员 C语言
C语言库函数 — 内存函数(含模拟实现内存函数)
C语言库函数 — 内存函数(含模拟实现内存函数)
15 0
|
8天前
|
存储 编译器 C语言
深入探索C语言动态内存分配:释放你的程序潜力
深入探索C语言动态内存分配:释放你的程序潜力
26 0
|
6天前
|
程序员 C语言 开发者
C语言库函数 — 字符串函数(含模拟实现字符串函数)
C语言库函数 — 字符串函数(含模拟实现字符串函数)
30 0
|
9天前
|
存储 测试技术 C语言
【C语言进阶】 假期测评③
【C语言进阶】 假期测评③
37 1
|
12天前
|
存储 C语言
【我爱C语言】详解字符函数isdigit和字符串转换函数(atoi和snprintf实现互相转换字符串)&&三种strlen模拟实现1
【我爱C语言】详解字符函数isdigit和字符串转换函数(atoi和snprintf实现互相转换字符串)&&三种strlen模拟实现
|
12天前
|
机器学习/深度学习 C语言
【C语言】函数的系统化精讲(三)1
【C语言】函数的系统化精讲(三)
|
12天前
|
编译器 C语言
【C语言】函数的系统化精讲(一)2
【C语言】函数的系统化精讲(一)2
|
12天前
|
编译器 Serverless C语言
【C语言】函数的系统化精讲(一)1
【C语言】函数的系统化精讲(一)
|
12天前
|
存储 程序员 编译器
【C语言第二回】main、printf和库函数
【C语言第二回】main、printf和库函数
|
17天前
|
编译器 C语言 C++
【C语言】calloc()函数详解(动态内存开辟函数)
【C语言】calloc()函数详解(动态内存开辟函数)
23 0