C/C++字符函数和字符串函数模拟实现与详解————长度不受限制的字符串函数

简介: C/C++字符函数和字符串函数模拟实现与详解————长度不受限制的字符串函数

1.前言

       对于字符串这一部分我们想到的大部分是字符串的创建,const修饰字符串,指针指向字符串,字符指针,字符数组这些内容,实际上在C语言中有一些字符函数和字符串函数。C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串 中或者 字符数组中。字符串常量 适用于那些对它不做修改的字符串函数。

2strlen函数

       对于strlen函数我们可以访问cplusplus网站cplusplus进行查阅,看一看strlen函数的参数是什么以及返回类型是什么样子的。

        我们看到strlen函数的返回类型是size_t类型也就是无符号整数,它的类型是const char*str也就是字符串的地址,说到这里你有没有想到我们前面的笔试题,为什么在参数放字符元素会报错误,就是因为这里应该放字符的地址,由于字符串是用ASCLL码进行储存,二进制转化为十六进制,整形提升,就会形成一个野指针,产生报错。这个函数是计算字符的个数遇到’\0'结束,不计算’\0';例如我们想要计算某个字符串的长度,代码如下:

#include<stdio.h>
#include <string.h>
int main()
{
  char arr[] = "abcdef";
  size_t sz = strlen(arr);
  printf("%d\n", sz);
  return 0;
}

运行结果如下:

我们可以模拟实现一个strlen函数代码如下:

#include<stdio.h>
int my_strlen(const char* str)
{
  const char* p = str;
  while (*p != '\0')
  {
    p++;
  }
  return p - str;
}
int main()
{
  char arr[] = "abcdef";
  int ret = my_strlen(arr);
  printf("%d", ret);
  return 0;
}

       在这里我们主要用到指针减指针来计算字符的个数,当然我们也可以通过计数器或递归来进行操作,在这里不进行详细讲解。

3.strcpy函数

       我们进入cplusplus网站进行查阅strcpy的参数

        我们可以看到strcpy函数的返回类型是char*参数是 char * destination, const char * source

第一个参数是想要修改的字符串的指针,第二个参数是想要得到的字符出的指针由于第二个参数不需要我们修改,难免会出现错误,用const进行修饰。特别注意我们需要保证源字符串的长度必须大于第二个字符串的长度,否则会造成栈溢出的问题,导致程序崩溃。例如我们可以写一个程序来感受一下此函数的功能,代码如下:

#include<stdio.h>
#include <string.h>
int main()
{
  char arr[] = "abcdef";
  char arr1[] = "aaa";
  strcpy(arr, arr1);
  printf("%s\n", arr);
  return 0;
}

运行结果如下:

我们对函数strcpy进行模拟,代码如下:

#include<stdio.h>
#include<assert.h>
void my_strcpy(char* str1, const char* str2)
{
  assert(str1 && str2);
  char* p = str1;
  while (*str2 != '\0')
  {
    *p = *str2;
    p++;
    str2++;
  }
}
int main()
{
  char arr[20] = { 'a','b','c'};
  const char arr2[] = "ba";
  my_strcpy(arr, arr2);
  printf("%s", arr);
}

       在这个函数中我们就是先记录字符串的首元素的地址,再定义指针进行赋值,直到‘\0’赋值完成,返回首元素的指针。

4.strcat函数

        我们进入cplusplus网站进行查阅strcat的参数

       此函数的返回类型是char*,参数是char * destination, const char * source,和strcpy函数一样它的第一个参数是想要修改的字符串的指针,第二个参数是想要得到的字符出的指针由于第二个参数不需要我们修改,难免会出现错误,用const进行修饰。我们想要进行字符串的连接,代码如下

#include<stdio.h>
#include <string.h>
int main()
{
  char arr[100] = { 'a','b'};
  char arr1[] = "aaa";
  strcat(arr, arr1);
  printf("%s\n", arr);
  return 0;
}

运行结果如下:

我们对strcat函数进行模拟,代码如下:

#include<stdio.h>
#include<assert.h>
void my_strcat(char* str1, const char* str2)
{
  assert(str1 && str2);
  char* p = str1;
  while (*p != '\0')
  {
    p++;
  }
  while (*str2 != '\0')
  {
    *p = *str2;
    p++;
    str2++;
  }
  *p = *str2;
}
int main()
{
  char arr[20] = { 'a','b','d','e','f' };
  const char arr2[] = "ghi";
  my_strcat(arr, arr2);
  printf("%s", arr);
  return 0;
}

       在这里我们就是需要一个指针记录字符串的位置,一个移动,直到出现’\0‘然进修修改,注意需要两个字符串的总长度小于第一个字符串的容量。

5.strcmp函数

       此函数的返回类型是int,由于是对两个字符串进行比较所以不需要对字符串进行修改,所以用const进行修饰。

       它的返回值是整形,如果第一个字符串大于第二个返回大于0的数,小于返回小于0的数,等于返回0,比较就是逐个进行比较从第一个开始,相同则后移比较不同则进行比较返回结果。例如代码:

#include<stdio.h>
#include <string.h>
int main()
{
  const char arr[] = "abcdefg";
  const char arr2[] = "abcdf";
  int ret = strcmp(arr, arr2);
  if (ret > 0)
  {
    printf(">");
  }
  else if (ret < 0)
  {
    printf("<");
  }
  else
  {
    printf("=");
  }
  return 0;
}

运行结果如下:

我们对strcmp进行模拟实现,代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
  assert(str1&& str2);
  while (*str1 == *str2)
  {
    str1++;
    str2++;
  }
  return *str1 - *str2;
}
int main()
{
  const char arr[] = "abcdefg";
  const char arr2[] = "abcdf";
  int ret = my_strcmp(arr, arr2);
  if (ret > 0)
  {
    printf(">");
  }
  else if (ret < 0)
  {
    printf("<");
  }
  else
  {
    printf("=");
  }
  return 0;
}

和上面叙述的一样,先找到不同的字符,进行相减,然后判断。

今天的内容就结束了希望大家可以一键三连。

 

目录
相关文章
|
4月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
4月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
163 6
|
4月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
62 0
|
4月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
46 3
|
4月前
|
安全 编译器 C++
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
【C++篇】C++类与对象深度解析(三):类的默认成员函数详解
45 3
|
4月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
709 1
|
4月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
67 1
|
4月前
|
安全 C语言 C++
|
4月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
92 0
C++入门6——模板(泛型编程、函数模板、类模板)
|
4月前
|
存储 编译器 C++
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作(三)
【C++】掌握C++类的六个默认成员函数:实现高效内存管理与对象操作