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

简介: 这是重写C语言string.c的部分函数的第3篇文章,前面2篇文章已经重写了部分函数,这篇文章介绍剩下的几个常用函数重写方法。

一、函数介绍

这是重写C语言string.c的部分函数的第3篇文章,前面2篇文章已经重写了下面几个函数:

strdup  字符串拷贝
strchr  字符查找函数 (从头开始)
strrchr 字符查找函数(从尾开始)
strcat strncat  字符串拼接函数
memset 内存初始化函数 (可用于赋初值)
strcmp  字符串比较
strlen  计算字符串长度
strstr  字符串查找
memcmp  内存比较
strcpy  字符串拷贝
memcpy  内存拷贝

这篇文章继续重新的函数如下:

strspn  字符查找 (详细介绍看重写的源码介绍和示例代码)
strpbrk 字符查找函数(查找第一个匹配的字符)
strtok、strsep  字符串分隔---字符串处理中非常常用
bcopy   内存拷贝 与memcpy() 功能相同
memscan、memchr 在内存区域中查找字符

二、重写函数源码

2.1 strspn字符查找

strspn 从参数s字符串的开头查找计算连续的字符,这些字符都是accept字符串中包含的字符。

size_t strspn(const char *s, const char *accept)
{
    const char *p;
    const char *a;
    size_t count = 0;

    for (p = s; *p != '\0'; ++p) {
        for (a = accept; *a != '\0'; ++a) {
            if (*p == *a)
                break;
        }
        if (*a == '\0')
            return count;
        ++count;
    }

    return count;
}

示例:
#include <stdio.h>
#include <string.h>
int main()
{
    int i;
    char str[] = "123";
    char accept[] = "1111123hhhhh123hhhhh123hhhhh123hhhh";
    i = strspn(str, accept);
    printf("查找的结果: %d\n", i);
    return 0;
}

2.2 strpbrk字符查找函数(顺序遍历)

strpbrk函数是在源字符串cs中查找最先含有搜索字符串ct中任一字符的位置并返回,如果找不到就返回空指针NULL。
比如: 查找的源字符串是 abcd
要查找的字符串还是78c,那么查找的结果返回就是c。 因为查找的字符串里c在源字符串里匹配。

char * strpbrk(const char * cs,const char * ct)
{
    const char *sc1,*sc2;

    for( sc1 = cs; *sc1 != '\0'; ++sc1) {
        for( sc2 = ct; *sc2 != '\0'; ++sc2) {
            if (*sc1 == *sc2)
                return (char *) sc1;
        }
    }
    return NULL;
}

示例:
#include <stdio.h>
#include <string.h>
int main()
{
    const char str1[] = "1234567890abcdefg";
    const char str2[] = "Mbc";
    const char *find_str =NULL;

    find_str = strpbrk(str1, str2);
    if (find_str)
    {
        printf("第一个匹配的字符是: %c\n", *find_str); //b
    }
    else
    {
        printf("未查找到字符");
    }
    return 0;
}

2.3 strtok 字符串分隔

strtok函数 用于字符串的分隔,可以根据特定的字符串、字符分隔字符串,字符串处理比较常用。

strtok函数第一次调用时会把ct字符串中所有在s中出现的字符替换为NULL。然后通过依次调用strtok(NULL, ct)得到各部分子串,详细使用方法看下面的示例代码。

/**
*strtok-将字符串拆分为标记
*/
char * ___strtok;
char * strtok(char * s,const char * ct)
{
    char *sbegin, *send;

    sbegin  = s ? s : ___strtok;
    if (!sbegin) {
        return NULL;
    }
    sbegin += strspn(sbegin,ct);
    if (*sbegin == '\0') {
        ___strtok = NULL;
        return( NULL );
    }
    send = strpbrk( sbegin, ct);
    if (send && *send != '\0')
        *send++ = '\0';
    ___strtok = send;
    return (sbegin);
}


示例代码:
#include <stdio.h>
#include <string.h>
int main()
{
    char str1[] = "123-456-789-abc";
    const char str2[] = "-";
    char *find_str =NULL;

    find_str = strtok(str1, str2);
    if (find_str)
    {
        printf("分隔的字符串: %s\n", find_str);
        while (1)
        {
            find_str = strtok(NULL, str2);
            if (find_str)
            {
                printf("分隔的字符串: %s\n", find_str);
            }
            else
            {
                break;
            }
        }
    }
    return 0;
}

/*
分隔的字符串: 123
分隔的字符串: 456
分隔的字符串: 789
分隔的字符串: abc
* */

strtok的升级版本是strsep函数。

char * strsep(char **s, const char *ct)
{
    char *sbegin = *s, *end;

    if (sbegin == NULL)
        return NULL;

    end = strpbrk(sbegin, ct);
    if (end)
        *end++ = '\0';
    *s = end;

    return sbegin;
}

2.4 bcopy 内存拷贝函数

bcopy 与memcpy 功能一样,但是不检查NULL结尾。

/**
*bcopy-将内存的一个区域复制到另一个区域
*@src:从何处复制
*@dest:复制到哪里
*@count:该区域的大小。
bcopy() 和 memcpy() 功能相同,用来复制内存块的前 n 个字节
需要注意的是 bcopy 与memcpy()相同,参数相反。
*/
char * bcopy(const char * src, char * dest, int count)
{
    char *tmp = dest;

    while (count--)
        *tmp++ = *src++;

    return dest;
}

2.5 memscan 在内存区域中查找字符

memscan 用于在内存区域中查找字符,addr是查找的内存首地址,c是查找的字符,size查找的区域范围.

如果查找成功就返回该字符在内存里的地址,如果没有查找到就返回查找的内存的首地址。

void * memscan(void * addr, int c, size_t size)
{
    unsigned char * p = (unsigned char *) addr;

    while (size) {
        if (*p == c)
            return (void *) p;
        p++;
        size--;
    }
    return (void *) p;
}

memchr功能:

从s所指内存区域的前n个字节查找字符c,当第一次遇到字符c时停止查找,如果成功,返回指向字符c的指针;否则返回NULL。

void *memchr(const void *s, int c, size_t n)
{
    const unsigned char *p = s;
    while (n-- != 0) {
        if ((unsigned char)c == *p++) {
            return (void *)(p-1);
        }
    }
    return NULL;
}
目录
相关文章
|
8天前
|
存储 Serverless C语言
【C语言基础考研向】11 gets函数与puts函数及str系列字符串操作函数
本文介绍了C语言中的`gets`和`puts`函数,`gets`用于从标准输入读取字符串直至换行符,并自动添加字符串结束标志`\0`。`puts`则用于向标准输出打印字符串并自动换行。此外,文章还详细讲解了`str`系列字符串操作函数,包括统计字符串长度的`strlen`、复制字符串的`strcpy`、比较字符串的`strcmp`以及拼接字符串的`strcat`。通过示例代码展示了这些函数的具体应用及注意事项。
|
11天前
|
存储 C语言
C语言程序设计核心详解 第十章:位运算和c语言文件操作详解_文件操作函数
本文详细介绍了C语言中的位运算和文件操作。位运算包括按位与、或、异或、取反、左移和右移等六种运算符及其复合赋值运算符,每种运算符的功能和应用场景都有具体说明。文件操作部分则涵盖了文件的概念、分类、文件类型指针、文件的打开与关闭、读写操作及当前读写位置的调整等内容,提供了丰富的示例帮助理解。通过对本文的学习,读者可以全面掌握C语言中的位运算和文件处理技术。
|
11天前
|
存储 C语言
C语言程序设计核心详解 第七章 函数和预编译命令
本章介绍C语言中的函数定义与使用,以及预编译命令。主要内容包括函数的定义格式、调用方式和示例分析。C程序结构分为`main()`单框架或多子函数框架。函数不能嵌套定义但可互相调用。变量具有类型、作用范围和存储类别三种属性,其中作用范围分为局部和全局。预编译命令包括文件包含和宏定义,宏定义分为无参和带参两种形式。此外,还介绍了变量的存储类别及其特点。通过实例详细解析了函数调用过程及宏定义的应用。
|
17天前
|
Linux C语言
C语言 多进程编程(三)信号处理方式和自定义处理函数
本文详细介绍了Linux系统中进程间通信的关键机制——信号。首先解释了信号作为一种异步通知机制的特点及其主要来源,接着列举了常见的信号类型及其定义。文章进一步探讨了信号的处理流程和Linux中处理信号的方式,包括忽略信号、捕捉信号以及执行默认操作。此外,通过具体示例演示了如何创建子进程并通过信号进行控制。最后,讲解了如何通过`signal`函数自定义信号处理函数,并提供了完整的示例代码,展示了父子进程之间通过信号进行通信的过程。
|
17天前
|
C语言
C语言 字符串操作函数
本文档详细介绍了多个常用的字符串操作函数,包括 `strlen`、`strcpy`、`strncpy`、`strcat`、`strncat`、`strcmp`、`strncpy`、`sprintf`、`itoa`、`strchr`、`strspn`、`strcspn`、`strstr` 和 `strtok`。每个函数均提供了语法说明、参数解释、返回值描述及示例代码。此外,还给出了部分函数的自实现版本,帮助读者深入理解其工作原理。通过这些函数,可以轻松地进行字符串长度计算、复制、连接、比较等操作。
|
18天前
|
SQL 关系型数据库 C语言
PostgreSQL SQL扩展 ---- C语言函数(三)
可以用C(或者与C兼容,比如C++)语言编写用户自定义函数(User-defined functions)。这些函数被编译到动态可加载目标文件(也称为共享库)中并被守护进程加载到服务中。“C语言函数”与“内部函数”的区别就在于动态加载这个特性,二者的实际编码约定本质上是相同的(因此,标准的内部函数库为用户自定义C语言函数提供了丰富的示例代码)
|
24天前
|
编译器 C++ 容器
【C++】String常见函数用法
【C++】String常见函数用法
15 1
|
29天前
|
数据采集 自动驾驶 算法
C语言自动驾驶实战项目:基于激光雷达的实时路径规划与避障系统
C语言自动驾驶实战项目:基于激光雷达的实时路径规划与避障系统
55 0
|
29天前
|
机器学习/深度学习 编译器 Serverless
C语言中函数
C语言中函数
19 0
|
29天前
|
存储 Serverless C语言
C语言中的标准库函数
C语言中的标准库函数
23 0