C语言模拟实现字符串库函数的示例讲解

 更新时间:2023年01月13日 15:38:08   作者:叫我小秦就好了  
这篇文章主要为大家详细介绍了C语言模拟实现字符串库函数的具体方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

字符串检验

strlen

函数原型

/// @brief 返回给定空终止字符串的长度,即首元素为 str 所指,且不包含首个空字符的字符数组中的字符数
/// @param str 指向要检测的字符串的指针
/// @return 字符串 str 的长度
size_t strlen( const char *str );

空终止字符串即 C 语言中以 ‘\0’ 作为终止符的字符串,strlen 计算字符串的长度并返回,返回的长度不包含 ‘\0’。

char arr[] = "qgw";
// num 的值是 3
int num = strlen(arr);

模拟实现

下面的实现方式比较简单,采用遍历字符串的方式,遇到 ‘\0’ 就退出循环,返回结果。

size_t my_strlen(const char* str) {
    size_t cnt = 0;
    while (*str != '\0') {
        ++str;
        ++cnt;
    }
    return cnt;
}

strcmp

函数原型

/// @brief 以字典序比较二个字符串
/// @param str rhs 要比较的两字符串
/// @return 相等返回 0
int strcmp(const char* lhs, const char* rhs);

返回值:

  • 两字符串字典序相同,返回 0
  • lhs 字典序大于 rhs,返回一个正数
  • lhs 字典序小于 rhs,返回一个负数

模拟实现

实现的思路是:遍历两个字符串,直到出现不同或有字符串结束。

res 存储两字符串比较的结果,如果等于 0 循环继续,不等于 0 直接退出,lhs 指向的字符大于 rhs 指向的字符就为正数,否则反之。

若 lhs 先结束,rhs 还没结束,此时 res 为负数,\0 的 ASCII 码为 0,是最小的。若 rhs 先结束,lhs 还没结束,此时 res 为正数。若同时结束,res 刚好为 0 返回。

int my_strcmp(const char* lhs, const char* rhs) {
    int res = 0;
    while ((res = *lhs - *rhs) == 0 && *lhs != '\0' && *rhs != '\0') {
        ++lhs;
        ++rhs;
    }
    return res;
}

strstr

函数原型

/// @brief 在 str 中查找 substr 子串
/// @param str 指向要检验的空终止字符串的指针
/// @param substr 指向要查找的空终止字节字符串的指针
/// @return 指向于 str 中找到的子串首字符的指针,或若找不到该子串则为空指针
char *strstr( const char* str, const char* substr );

若 substr 指向空,则会返回 str。

模拟实现

下面实现的方法为暴力匹配子串,实际中可以使用 KMP 或 BM 等字符串搜索函数优化这一过程。

char* my_strstr(const char* str, const char* substr) {
	if (substr == NULL) {
		return str;
	}

	// 遍历 str 所有字符,看以其起始字符是否匹配
	while (*str != '\0') {
		const char* backStr = str;
		const char* backSub = substr;
		while (*backStr != '\0' && *backSub != '\0' && *backStr == *backSub) {
			++backStr;
			++backSub;
		}
		// 如果 substr 走完了,说明匹配成功了,返回此时的 str
		if (*backSub == '\0') {
			return str;
		}
		++str;
	}
}

字符串操作

strcpy

函数原型

/// @brief 复制 src 所指向的空终止字符串,包含空终止符,到首元素为 dest 所指的字符数组
/// @param dest 指向要写入的字符数组的指针
/// @param src 指向要复制的空终止字符串的指针
/// @return 返回 dest 的副本
char *strcpy( char *dest, const char *src );

需要注意的是:

1.若 dest 数组长度不足则行为未定义

即 dest 数组不足以包含 src 中所有元素,此时大概率会因越届访问崩溃

2.若字符串覆盖则行为未定义

现在主流编译器都可以处理有覆盖的情况,比如:MSVC、GCC

3.若 dest 不是指向字符数组的指针或 src 不是指向空终止字符串的指针则行为未定义

模拟实现

下面的方法先记录要返回的地址,最后遍历 src 遇到 \0,此时退出循环。

注意:该实现方法并不能解决字符串有覆盖的情况。

char* my_strcpy(char* dest, const char* src) {
    char* res = dest;
    while (*dest = *src) {
        ++dest;
        ++src;
    }
    return res;
}

strcat

函数原型

/// @brief 后附 src 所指向的空终止字符串的副本到 dest 所指向的空终止字符串的结尾
/// @param dest 指向要后附到的空终止字符串的指针
/// @param src 指向作为复制来源的空终止字符串的指针
/// @return 返回 dest 的副本
char *strcat( char *dest, const char *src );

需要注意的是:

会用字符 src[0] 替换 dest 末尾的 \0

若目标数组对于 src 和 dest 的内容以及空终止符不够大,则行为未定义

若字符串重叠,则行为未定义

若 dest 或 src 不是指向空终止字符串的指针,则行为未定义

模拟实现

因为会先用 src 第一个字符替换 dest 结尾的 \0,所以要先找到 dest 结尾 \0。然后再遍历 src,将其添加到 dest 结尾。

char* my_strcat(char* dest, const char* src) {
    char res = dest;
    // 先找 \0 的位置
    while (*dest != '\0') {
        ++dest;
    }
    // 追加到 dest 后面
    while (*dest = *src) {
        ++dest;
        ++src;
    }
    return res;
}

内存操作

memcpy

函数原型

/// @brief 从 src 所指向的对象复制 count 个字符到 dest 所指向的对象
/// @param dest 指向要复制的对象的指针
/// @param src 指向复制来源对象的指针
/// @param count 复制的字节数
/// @return 返回 dest 的副本
void* memcpy(void* dest, const void* src, size_t count);

要注意的是:

若访问发生在 dest 数组结尾后则行为未定义

若对象重叠,则行为未定义

也就是说在标准中 memcpy 也不能处理对象重叠的情况

若 dest 或 src 为非法或空指针则行为未定义

模拟实现

下面给出的实现方式与 strcpy 相似,不过是改用 count 变量来控制循环次数。

memcpy 是最快的内存到内存复制子程序。它通常比必须扫描其所复制数据的 strcpy,或必须预防以处理重叠输入的 memmove更高效。

void* my_memcpy(void* dest, const void* src, size_t count) {
    void* res = dest;
    while (count--) {
        *(char*)dest = *(char*)src;
        ++(char*)dest;
        ++(char*)src;
    }
    return res;
}

memmove

函数原型

/// @brief 从 src 所指向的对象复制 count 个字节到 dest 所指向的对象
/// @param dest 指向要复制的对象的指针
/// @param src 指向复制来源对象的指针
/// @param count 复制的字节数
/// @return 返回 dest 的副本
void* memmove(void* dest, const void* src, size_t count);

memmove 是不是看起来和 memcpy 一模一样,但 memmove 可以处理内存重叠的情况,这也就说明它要做一些检查,来保证能够处理内存重叠的情况。

1.无重叠

直接调用更高校的 memcpy

2.有重叠,dest 在 src 之前,正常正向复制

3.有重叠,dest 在 src 之后,需要反向复制

模拟实现

通过对上图的观察,我们可以发现:若 dest 在 src 的后面并且存在内存重叠,就需要反向复制。

我们可以简化这一函数,对无重叠的情况不去调用 memcpy 而是包含在下面两种情况中。

dest 在 src 之前,采用正向复制

dest 在 src 之后,采用反向复制

void* my_memmove(void* dest, const void* src, size_t count) {
    void* res = dest;
    if (dest < src) {
        while (count--) {
            *(char*)dest = *(char*)src;
            ++(char*)dest;
            ++(char*)src;
        }
    } else {
        while (count--) {
            *((char*)dest + count) = *((char*)src + count);
        }
    }
}

到此这篇关于C语言模拟实现字符串库函数的示例讲解的文章就介绍到这了,更多相关C语言字符串库函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现职工工资管理系统课程设计

    C++实现职工工资管理系统课程设计

    这篇文章主要为大家详细介绍了C++实现职工工资管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++11中longlong超长整型和nullptr初始化空指针

    C++11中longlong超长整型和nullptr初始化空指针

    本文介绍 C++11 标准中新添加的 long long 超长整型和 nullptr 初始化空指针,在 C++11 标准下,相比 NULL 和 0,使用 nullptr 初始化空指针可以令我们编写的程序更加健壮,本文结合示例代码给大家详细讲解,需要的朋友跟随小编一起看看吧
    2022-12-12
  • C++ Boost Random随机函数详解

    C++ Boost Random随机函数详解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C语言实现动态开辟存储杨辉三角

    C语言实现动态开辟存储杨辉三角

    这篇文章主要介绍了如何利用C语言实现动态开辟存储杨辉三角,可以灵活的开辟空间,充分的利用空间。文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下
    2022-03-03
  • C语言实现高精度减法

    C语言实现高精度减法

    高精度的本质是将数字以字符串的形式读入,然后将每一位分别存放入int数组中,通过模拟每一位的运算过程,来实现最终的运算效果,下面我们就来看看C语言如何实现高精度减法吧
    2023-11-11
  • C语言中带头双向循环链表基本操作的实现详解

    C语言中带头双向循环链表基本操作的实现详解

    无头单向非循环链表结构简单,一般不会单独用来存数据。而带头双向循环链表的结构较为复杂,一般用在单独存储数据。本文将介绍带头双向循环链表的基本操作,需要的可以参考一下
    2022-11-11
  • QT线程池的使用(QThreadPool类和QRunnable类)

    QT线程池的使用(QThreadPool类和QRunnable类)

    本文主要介绍了QT线程池的使用(QThreadPool类和QRunnable类),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04
  • C语言简易实现扫雷小游戏

    C语言简易实现扫雷小游戏

    这篇文章主要为大家详细介绍了C语言简易实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • C中实现矩阵乘法的一种高效的方法

    C中实现矩阵乘法的一种高效的方法

    本篇文章介绍了,在C中实现矩阵乘法的一种高效的方法。需要的朋友参考下
    2013-05-05
  • C语言超全面讲解字符串函数

    C语言超全面讲解字符串函数

    字符串函数(String processing function)也叫字符串处理函数,指的是编程语言中用来进行字符串处理的函数,如C,pascal,Visual以及LotusScript中进行字符串拷贝,计算长度,字符查找等的函数
    2022-06-06

最新评论