C语言-重构string.c系统库函数(1)

简介: string.h里主要包含了C语言对字符串操作的相关函数,这篇文章就介绍几个比较常用的函数重新自己实现。

一、string.c里相关函数介绍

string.h里主要包含了C语言对字符串操作的相关函数,这篇文章就介绍几个比较常用的
函数重新自己实现。并且每个函数给出了2种以上的不同写法,全部采用指针方式;在学习C语言过程中,重写这些字符串处理函数可以快速提升、磨练自己的指针、数组、函数相关知识,对学习是非常有帮助的;在单片机、嵌入式开发中,也会经常需要自己实现这些函数,可能有些功能系统函数不能满足的情况下,都需要自己重新实现。

二、重写函数介绍

2.1 strcmp : 字符串比较

字符串比较函数,用来比较两个字符串是否相等,下面给出了4种写法,其中一个是strncmp函数。

int strcmp(const char *str1, const char *str2)
{
    const unsigned char *s1 = (const unsigned char *)str1;
    const unsigned char *s2 = (const unsigned char *)str2;
    int delta = 0;

    while (*s1 || *s2) {
        delta = *s2 - *s1;
        if (delta)
            return delta;
        s1++;
        s2++;
    }
    return 0;
}

int strncmp(const char *cs, const char *ct, size_t count)
{
    unsigned char c1, c2;
    while (count) {
        c1 = *cs++;
        c2 = *ct++;
        if (c1 != c2)
            return c1 < c2 ? -1 : 1;
        if (!c1)
            break;
        count--;
    }
    return 0;
}


int strcmp(const char *a, const char *b)
{
    while (*a || *b) {
        if (*a != *b)
            return 1;
        if (*a == 0 || *b == 0)
            return 1;
        a++;
        b++;
    }
    return 0;
}

int strcmp(const char *cs, const char *ct)
{
    unsigned char c1, c2;
    int res = 0;
    do {
        c1 = *cs++;
        c2 = *ct++;
        res = c1 - c2;
        if (res)
            break;
    } while (c1);
    return res;
}

2.2 strlen: 字符串长度介绍

strlen是计算字符串长度的函数,比较常用,代码也最简单,下面写了两种实现方法。

size_t strlen(const char *s)
{
    const char *sc = s;
    while (*sc != '\0')
        sc++;
    return sc - s;
}

size_t strlen(const char *s)
{
    const char *sc;
    for (sc = s; *sc != '\0'; ++sc)
    return sc - s;
}

size_t strnlen(const char *s, size_t count)
{
    const char *sc;
    for (sc = s; count-- && *sc != '\0'; ++sc)
    return sc - s;
}

2.3 strstr: 字符串查找

strstr字符串查找函数,用来查找指定的字符串在源字符串里是否存在,存在就返回地址。
这个就给出了一种写法。

char *strstr(const char *s1, const char *s2)
{
    size_t l1, l2;
    l2 = strlen(s2);
    if (!l2)
        return (char *)s1;
    l1 = strlen(s1);
    while (l1 >= l2) {
        l1--;
        if (!memcmp(s1, s2, l2))
            return (char *)s1;
        s1++;
    }
    return NULL;
}

2.4 memcmp : 内存比较

memcmp内存比较函数,用来比较两个内存地址里的数据是否相等,不局限于字符串,只要是合法内存都可以按字节比较。

int memcmp(const void *cs, const void *ct, size_t count)
{
    const unsigned char *su1 = cs, *su2 = ct, *end = su1 + count;
    int res = 0;
    while (su1 < end) {
        res = *su1++ - *su2++;
        if (res)
            break;
    }
    return res;
}


int memcmp(const void *cs, const void *ct, size_t count)
{
    const unsigned char *su1, *su2;
    int res = 0;
    for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
        if ((res = *su1 - *su2) != 0)
            break;
    return res;
}

2.5 strcpy :字符串拷贝

strcpy字符串拷贝函数,用来将目标字符串拷贝到指定的地址中。目标字符串必须是‘\0’结束。 这里写了2种函数,一个strcpy、一个strncpy。

char *strcpy(char *dest, const char *src)
{
    char *tmp = dest;
    while ((*dest++ = *src++) != '\0')
    return tmp;
}

char *strncpy(char *dest, const char *src, size_t count)
{
    char *tmp = dest;

    while (count) {
        if ((*tmp = *src) != 0)
            src++;
        tmp++;
        count--;
    }
    return dest;
}

size_t strlcpy(char *dest, const char *src, size_t size)
{
    size_t ret = strlen(src);

    if (size) {
        size_t len = (ret >= size) ? size - 1 : ret;
        memcpy(dest, src, len);
        dest[len] = '\0';
    }
    return ret;
}

2.6 内存拷贝: memcpy

内存拷贝函数,将目标内存数据拷贝导致指定内存位置,不局限于字符串。

void *memcpy(void *__dest, __const void *__src, size_t __n)
{
    int i = 0;
    unsigned char *d = (unsigned char *)__dest, *s = (unsigned char *)__src;
    for (i = __n >> 3; i > 0; i--) {
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
    }
    if (__n & 1 << 2) {
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
        *d++ = *s++;
    }
    if (__n & 1 << 1) {
        *d++ = *s++;
        *d++ = *s++;
    }
    if (__n & 1)
        *d++ = *s++;
    return __dest;
}

void *memcpy(void *__dest, __const void *__src, size_t __n)
{
    int i;
    char *d = (char *)__dest, *s = (char *)__src;
    for (i = 0; i < __n; i++)
        d[i] = s[i];
    return __dest;
}

static inline void *memcpy(void *__dest, const void *__src, size_t __n)
{
    int i;
    const char *s = __src;
    char *d = __dest;
    for (i = 0; i < __n; i++)
        d[i] = s[i];
    return __dest;
}
目录
相关文章
|
11天前
|
存储 算法 C语言
【C语言程序设计——函数】素数判定(头歌实践教学平台习题)【合集】
本内容介绍了编写一个判断素数的子函数的任务,涵盖循环控制与跳转语句、算术运算符(%)、以及素数的概念。任务要求在主函数中输入整数并输出是否为素数的信息。相关知识包括 `for` 和 `while` 循环、`break` 和 `continue` 语句、取余运算符 `%` 的使用及素数定义、分布规律和应用场景。编程要求根据提示补充代码,测试说明提供了输入输出示例,最后给出通关代码和测试结果。 任务核心:编写判断素数的子函数并在主函数中调用,涉及循环结构和条件判断。
49 23
|
11天前
|
算法 C语言
【C语言程序设计——函数】利用函数求解最大公约数和最小公倍数(头歌实践教学平台习题)【合集】
本文档介绍了如何编写两个子函数,分别求任意两个整数的最大公约数和最小公倍数。内容涵盖循环控制与跳转语句的使用、最大公约数的求法(包括辗转相除法和更相减损术),以及基于最大公约数求最小公倍数的方法。通过示例代码和测试说明,帮助读者理解和实现相关算法。最终提供了完整的通关代码及测试结果,确保编程任务的成功完成。
43 15
|
1月前
|
IDE 编译器 开发工具
【C语言】全面系统讲解 `#pragma` 指令:从基本用法到高级应用
在本文中,我们系统地讲解了常见的 `#pragma` 指令,包括其基本用法、编译器支持情况、示例代码以及与传统方法的对比。`#pragma` 指令是一个强大的工具,可以帮助开发者精细控制编译器的行为,优化代码性能,避免错误,并确保跨平台兼容性。然而,使用这些指令时需要特别注意编译器的支持情况,因为并非所有的 `#pragma` 指令都能在所有编译器中得到支持。
120 41
【C语言】全面系统讲解 `#pragma` 指令:从基本用法到高级应用
|
11天前
|
C语言
【C语言程序设计——函数】亲密数判定(头歌实践教学平台习题)【合集】
本文介绍了通过编程实现打印3000以内的全部亲密数的任务。主要内容包括: 1. **任务描述**:实现函数打印3000以内的全部亲密数。 2. **相关知识**: - 循环控制和跳转语句(for、while循环,break、continue语句)的使用。 - 亲密数的概念及历史背景。 - 判断亲密数的方法:计算数A的因子和存于B,再计算B的因子和存于sum,最后比较sum与A是否相等。 3. **编程要求**:根据提示在指定区域内补充代码。 4. **测试说明**:平台对代码进行测试,预期输出如220和284是一组亲密数。 5. **通关代码**:提供了完整的C语言代码实现
50 24
|
7天前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
46 16
|
6天前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
18 3
|
6天前
|
存储 算法 安全
【C语言程序设计——函数】分数数列求和1(头歌实践教学平台习题)【合集】
if 语句是最基础的形式,当条件为真时执行其内部的语句块;switch 语句则适用于针对一个表达式的多个固定值进行判断,根据表达式的值与各个 case 后的常量值匹配情况,执行相应 case 分支下的语句,直到遇到 break 语句跳出 switch 结构,若没有匹配值则执行 default 分支(可选)。例如,在判断一个数是否大于 10 的场景中,条件表达式为 “num> 10”,这里的 “num” 是程序中的变量,通过比较其值与 10 的大小关系来确定条件的真假。常量的值必须是唯一的,且在同一个。
11 2
|
10天前
|
存储 编译器 C语言
【C语言程序设计——函数】回文数判定(头歌实践教学平台习题)【合集】
算术运算于 C 语言仿若精密 “齿轮组”,驱动着数值处理流程。编写函数求区间[100,500]中所有的回文数,要求每行打印10个数。根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码。如果操作数是浮点数,在 C 语言中是不允许直接进行。的结果是 -1,因为 -7 除以 3 商为 -2,余数为 -1;注意:每一个数据输出格式为 printf("%4d", i);的结果是 1,因为 7 除以 -3 商为 -2,余数为 1。取余运算要求两个操作数必须是整数类型,包括。开始你的任务吧,祝你成功!
41 1
|
1月前
|
存储 编译器 C语言
【C语言】C语言的变量和声明系统性讲解
在C语言中,声明和定义是两个关键概念,分别用于告知编译器变量或函数的存在(声明)和实际创建及分配内存(定义)。声明可以多次出现,而定义只能有一次。声明通常位于头文件中,定义则在源文件中。通过合理组织头文件和源文件,可以提高代码的模块化和可维护性。示例包括全局变量、局部变量、函数、结构体、联合体、数组、字符串、枚举和指针的声明与定义。
58 12
|
1月前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
62 9

热门文章

最新文章