C语言 字符函数汇总,模拟实现各字符函数(炒鸡详细)

目录

求字符串长度

strlen

示例

模拟实现strlen

长度不受限制的字符串函数

strcpy

示例

模拟实现strcpy

strcat

模拟实现strcat

strcmp

示例 

模拟实现strcmp

长度受限制的字符串函数介绍

strncpy

示例

模拟实现strncpy

strncat

示例 

模拟实现strncat 

strncmp

示例

模拟实现strncmp

字符串查找

strstr

示例

模拟实现strstr

strtok

示例

模拟实现strtok

错误信息报告

strerror

示例 

字符分类函数


求字符串长度

strlen

size_t strlen ( const char * str );
  1. 字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包 '\0' )
  2. 参数指向的字符串必须要以 '\0' 结束。
  3. 注意函数的返回值为size_t,是无符号的

示例

 const char*str1 = "abcdef";
 const char*str2 = "bbb";
 if(strlen(str2)-strlen(str1)>0)
 {
     printf("str2>str1\n");
 } 
 else
 {
     printf("srt1>str2\n");
 }

模拟实现strlen

#include <stdio.h>

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

int main() {
    const char* str = "Hello, World!";
    size_t length = my_strlen(str);
    
    printf("字符串的长度为: %zu\n", length);
    
    return 0;
}

长度不受限制的字符串函数

strcpy

copy字符串到目标字符串,应该使用strcpy

char* strcpy(char * destination, const char * source)

  1. 源字符串必须以 '\0' 结束。
  2. 会将源字符串中的 '\0' 拷贝到目标空间。
  3. 目标空间必须足够大,以确保能存放源字符串。
  4. 目标空间必须可变

示例

    char name[20] = {0};
    strcpy(name, "zhang\0hai");
    printf("%s\n", name); // zhang

模拟实现strcpy

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

char arr1[] = "abc\0def";
char arr2[] = {0};
my_strcpy(arr2, arr1);
printf("%s\n", arr2); // abc

strcat

拼接字符串到目标字符串,应该使用strcat

char * strcat ( char * destination , const char * source );
  1. 源字符串必须以 '\0' 结束。
  2. 目标空间必须有足够的大,能容纳下源字符串的内容。
  3. 目标空间必须可修改。
    /* 同样 strcpy同strcpy大概一致,需保持足够大的空间,遇\0停止 */
    char arr1[] = "demo";
    // strcat(arr1, "emo");
    // printf("%s", arr1); // demoemo
    strcat(arr1, "em\0o");
    printf("%s", arr1); // demoem

模拟实现strcat

char *my_strcat(char *dest, const char *str)
{
    char *res = dest;
    assert(dest && str);
    while (*dest != '\0') // 找到目标空间的末尾\0
    {
        dest++;
    }
    while (*dest++ = *str++)
    {
        ;
    }
    return res;
}

char arr3[20] = "hello ";
my_strcat(arr3, "world");
printf("%s\n", arr3); // hello world

strcmp

两个字符串比较相等,应该使用strcmp

int strcmp ( const char * str1 , const char * str2 );

比较是基于字符的 ASCII 值来进行的。strcmp() 会逐个比较两个字符串对应位置上的字符的 ASCII 值,并按照以下规则返回结果:

当找到不同的字符时,根据其 ASCII 值的大小关系决定比较结果。较小的字符对应的字符串被认为是较小的。如果一个字符串是另一个字符串的前缀,则较短的字符串被认为是较小的。

strcmp() 是区分大小写的。大写字母的 ASCII 值小于小写字母的 ASCII 值。

strcmp() 返回一个整数,表示两个字符串的比较结果。

  1. 如果字符串相等,则返回 0。
  2. 如果第一个字符串小于第二个字符串,则返回一个负整数。
  3. 如果第一个字符串大于第二个字符串,则返回一个正整数。

下面是一些比较的示例:

  •      strcmp(“apple”, “apple”) 返回 0,因为两个字符串相等。
  •      strcmp(“apple”, “banana”) 返回一个负整数,因为 “apple” 的 ASCII 值小于 “banana”。
  •      strcmp(“banana”, “apple”) 返回一个正整数,因为 “banana” 的 ASCII 值大于 “apple”。
  •      strcmp(“apple”, “Apples”) 返回一个正整数,因为 ‘a’ 的 ASCII 值大于 ‘A’。

示例 

    char arr1[20] = "zhangsan";
    char arr2[20] = "zhangsanfeng";
    int res = strcmp(arr1, arr2);
    if (res < 0)
    {
        printf("<\n"); // <
    }
    else if (res == 0)
    {
        printf("=\0");
    }
    else
    {
        printf(">\0");
    }

模拟实现strcmp

int my_strcmp(const char *s1, const char *s2)
{
    assert(s1 && s2);
    while (*s1 == *s2)
    {
        if (*s1 == '\0')
        {
            return 0; // 如果全等 abc == abc
        }
        s1++;
        s2++;
    }
    return *s1 - *s2;
}

char arr4[] = "zhanghai";
char arr5[] = "zhanghai";
printf("%d\n", my_strcmp(arr4, arr5)); // 0

长度受限制的字符串函数介绍

strncpy

strncpy 函数用于从源字符串复制指定数量的字符到目标字符串中,如果源字符串长度小于指定长度,则会用空字符进行填充。

char * strncpy ( char * destination, const char * source, size_t num );

  1. 拷贝num个字符从源字符串到目标空间。
  2. 如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

示例

 在这个示例中,我们声明了一个目标字符串 dest,一个源字符串 src 以及要复制的字符数量 n。然后,我们使用 strncpy 函数将 src 中的前 n 个字符复制到 dest 中。最后,我们手动添加了一个结尾标记 \0,以确保目标字符串正确终止。最后,我们打印复制后的目标字符串 dest

请注意,要确保目标字符串 dest 的长度足够大,以容纳复制的字符和结尾标记。如果 n 大于等于源字符串的长度,那么目标字符串将没有结尾标记

#include <stdio.h>
#include <string.h>

int main() {
    char dest[20];
    const char* src = "Hello, World!";
    size_t n = 5;

    printf("源字符串: %s\n", src);
    printf("复制的字符数: %zu\n", n);

    strncpy(dest, src, n);
    dest[n] = '\0';  // 添加结尾标记

    printf("目标字符串: %s\n", dest);

    return 0;
}

模拟实现strncpy

#include <stdio.h>

char* my_strncpy(char* dest, const char* src, size_t n) {
    size_t i;
    for (i = 0; i < n && src[i] != '\0'; i++) {
        dest[i] = src[i];
    }
    for ( ; i < n; i++) {
        dest[i] = '\0';  // 如果源字符串长度小于 n,则用空字符填充
    }
    return dest;
}

int main() {
    char dest[20];
    const char* src = "Hello, World!";
    size_t n = 5;
    
    printf("源字符串: %s\n", src);
    printf("复制的字符数: %zu\n", n);
    
    my_strncpy(dest, src, n);
    
    printf("目标字符串: %s\n", dest);
    
    return 0;
}

strncat

char * strncat ( char * dest , const char * src , size_t n );

strncat 用于将指定长度的字符串拼接(追加)到目标字符串的末尾。

参数说明:

  • dest:目标字符串,要将源字符串拼接到其末尾的字符串。
  • src:源字符串,要拼接到目标字符串末尾的字符串。
  • n:要拼接的最大字符数,即 src 中要拷贝的字符数。

strncat 函数的作用是将 src 指向的字符串的前 n 个字符(如果 src 的长度小于 n 则拷贝整个字符串)追加到 dest 指向的字符串的末尾,并在目标字符串的末尾添加字符串结尾标志 \0

该函数会返回指向目标字符串 dest 的指针,即拼接后的字符串的起始地址。

需要注意的是,目标字符串 dest 必须有足够的空间来容纳源字符串 src 的字符。否则,会导致缓冲区溢出和未定义的行为。
同时,strncat 不会检查源字符串 src 是否符合 C 字符串的规范(即是否以 \0 结尾),因此要确保源字符串 src 以 \0 结尾,以避免结果不符合预期。

示例 

在这个示例中,我们通过 strncat 函数将源字符串 src 的前 7 个字符拼接到目标字符串 dest 的末尾。输出中的最后一行显示了拼接后的字符串 dest。由于目标字符串 dest 的长度限制在 20 个字符,所以只有部分字符被拼接进去,因此输出结果是 “Hello, Wo”。

#include <stdio.h>
#include <string.h>

int main() {
    char dest[20] = "Hello";
    const char* src = ", World!";
    size_t n = 7;

    printf("目标字符串: %s\n", dest); // 目标字符串: Hello
    printf("源字符串: %s\n", src);    // 源字符串: , World!
    printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7

    strncat(dest, src, n);

    printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo

    return 0;
}

模拟实现strncat 

#include <stdio.h>

char* strncat_sim(char* dest, const char* src, size_t n) {
    char* dest_start = dest; // 保存目标字符串的起始位置

    // 遍历目标字符串,直到达到结尾
    while (*dest != '\0') {
        dest++;
    }

    // 将源字符串中的字符逐个拼接到目标字符串中,直到达到指定的字符数 n 或源字符串结尾
    while (n > 0 && *src != '\0') {
        *dest = *src;
        dest++;
        src++;
        n--;
    }

    *dest = '\0'; // 添加结尾标记

    return dest_start; // 返回目标字符串的起始位置
}

int main() {
    char dest[20] = "Hello";
    const char* src = ", World!";
    size_t n = 7;

    printf("目标字符串: %s\n", dest); // 目标字符串: Hello
    printf("源字符串: %s\n", src);   // 源字符串: , World!
    printf("拼接的字符数: %zu\n", n); // 拼接的字符数: 7

    strncat_sim(dest, src, n);

    printf("拼接后的字符串: %s\n", dest); // 拼接后的字符串: Hello, Wo

    return 0;
}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

  1. 比较字符串: 函数可以比较两个字符串的前n个字符,n由调用函数时指定。
  2. 返回值: 如果 s1 小于 s2,函数返回一个负值;如果 s1 大于 s2,函数返回一个正值;如果两个字符串在前n个字符内相等,函数返回0。
  3. 字符串结束判断: 与标准库中的strncmp类似,如果某个字符串的前n个字符中包含了'\0'(即字符串结束符),则仅比较到该结束符为止。

示例

#include <stdio.h>
#include <string.h>

int main() {
    const char* str1 = "Hello";
    const char* str2 = "Hell";
    int n = 4;

    int result = strncmp(str1, str2, n);

    if (result == 0) {
        printf("两个字符串相等\n");
    } else if (result < 0) {
        printf("str1 小于 str2\n");
    } else {
        printf("str1 大于 str2\n"); // str1 大于 str2
    }

    return 0;
}

模拟实现strncmp

#include <stdio.h>

int custom_strncmp(const char *s1, const char *s2, size_t n) {
    for (size_t i = 0; i < n; i++) {
        if (s1[i] != s2[i]) {
            return (s1[i] - s2[i]);
        }
        if (s1[i] == '\0') {
            return 0;  // 达到了字符串结尾
        }
    }
    return 0;  // 前 n 个字符均相同
}

int main() {
    const char *s1 = "Hello";
    const char *s2 = "Hell";
    int result = custom_strncmp(s1, s2, 4);
    if (result < 0) {
        printf("s1 小于 s2\n");
    } else if (result > 0) {
        printf("s1 大于 s2\n"); // s1 大于 s2
    } else {
        printf("s1 等于 s2\n");
    }
    return 0;
}

字符串查找

strstr

查找小串在大串是否出现,返回出现小串往后的字符

char* strstr(const char* haystack, const char* needle);

  1. 主要用途:strstr() 函数经常用于在字符串中查找子串,例如查找某个单词在文本中的位置。
  2. 区分大小写:strstr() 是区分大小写的,即输入的字符串要求大小写完全匹配。
  3. 返回的指针:如果找到了 needle 字符串在 haystack 中的位置,返回的指针指向首次出现的子串;如果未找到,返回 NULL。

示例

    char email[] = "zpw@example.com.demo";
    char substr[] = "example.com";
    char *res = strstr(email, substr);
    if (res == NULL)
    {
        printf("子串不存在\n");
    }
    else
    {
        printf("%s", res); // example.com.demo
    }

模拟实现strstr

char *my_strstr(const char *str1, const char *str2)
{
    assert(str1 && str2);
    const char *s1 = str1; // 负责找大串
    const char *s2 = str2; // 负责找小串
    const char *p = str1;  // 每次大串的起始点
    while (*p)
    {
        s1 = p;
        s2 = str2;
        /* 大小串都没结束,并且当前大小串的字符相等则进入 */
        while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)
        {
            s1++;
            s2++;
        }
        /* 如果是因为 小串结束没有再次进到上面循环,那么说明大串中成功找到小串 */
        if (*s2 == '\0')
        {
            return (char *)p;
        }
        /* 大串结束了,或者大小串当前字符不相等都会走到这里,则继续++大串的起始查找点,开始下一轮 */
        p++;
    }
    return NULL;
}

char email[] = "zpw@example.com.demo";
char substr[] = "example.com";
char *p = my_strstr(email, substr);
printf("%s\n", p); // example.com.demo

strtok

分割字符串

char * strtok ( char * str, const char * sep ); 

  1. sep参数是个字符串,定义了用作分隔符的字符集合
  2. 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
  3. strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
  4. strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
  5. strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
  6. 如果字符串中不存在更多的标记,则返回 NULL 指针。

示例

    const char *sep = "@.";
    char eml[] = "zhanghai@bitejiuyeke.com.net";
    char cp[40] = {0};
    strcpy(cp, eml);
    char *ret = NULL;
    for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep))
    {
        /*
            zhanghai
            bitejiuyeke
            com
            net
         */
        printf("%s\n", ret);
    }

模拟实现strtok

#include <stdio.h>
#include <string.h>

char* custom_strtok(char* str, const char* delim) {
    static char* remaining = NULL;
    if (str != NULL) {
        remaining = str;
    }
    
    // 跳过开头的分隔符
    while (*remaining != '\0' && strchr(delim, *remaining) != NULL) {
        remaining++;
    }
    
    if (*remaining == '\0') {
        return NULL;
    }
    
    char* token = remaining;
    remaining = strpbrk(remaining, delim);
    
    if (remaining != NULL) {
        *remaining = '\0';
        remaining++;
    }
    
    return token;
}

int main() {
    char str[] = "Hello World! This is a test.";
    char delim[] = " ";
    
    char* token = custom_strtok(str, delim);
    while (token != NULL) {
        /*
            Hello
            World!
            This
            is
            a
            test.
        */
        printf("%s\n", token);
        token = custom_strtok(NULL, delim);
    }
    
    return 0;
}

错误信息报告

strerror

char * strerror ( int errnum );

示例 

在这个示例中,我们尝试打开一个不存在的文件。由于文件不存在,fopen函数将返回NULL。然后,我们使用errno变量获取最近一次错误的错误码,传递给strerror函数。strerror函数将错误码转换为对应的错误信息字符串。

在这里,strerror(errno)将返回"No such file or directory",因为我们尝试打开一个不存在的文件。我们通过printf函数将错误信息打印到控制台上。

#include <stdio.h>
#include <string.h>
#include <errno.h>

int main() {
    FILE* file = fopen("nonexistent_file.txt", "r");
    if (file == NULL) {
        printf("Failed to open file: %s\n", strerror(errno));
    }
    
    return 0;
}

字符分类函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/165429.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL数据库索引以及使用唯一索引实现幂等性

&#x1f4d1;前言 本文主要是MySQL数据库索引以及使用唯一索引实现幂等性的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f30…

数据结构:红黑树讲解(C++)

红黑树 1.前言2.红黑树简述2.1概念2.2性质 3.红黑树的插入3.1关于新插入节点的颜色3.2节点的定义3.3插入新节点3.4判断插入后是否需要调整3.5插入后维持红黑树结构&#xff08;重点&#xff09;3.5.1cur、p、u为红&#xff0c;g为黑3.5.2cur、p为红&#xff0c;g为黑&#xff0…

MISRA 2012学习笔记(5)-Rules 8.10

文章目录 Rules8.10 基本类型模型(The essential type model)8.10.1 原理8.10.2 基本类型(Essential type)Rule 10.1 操作数不得具有不适当的基本类型Rule 10.2 在加减法运算中&#xff0c;不得不当使用本质为字符类型的表达式Rule 10.3 表达式的值不得赋值给具有较窄基本类型或…

【数据结构(二)】单链表(3)

文章目录 1. 链表介绍2. 单链表应用实例2.1. 顺序添加方式2.1.1. 思路分析2.1.2. 代码实现 2.2. 按照编号顺序添加方式2.2.1. 思路分析2.2.2. 代码实现 3. 单链表节点的修改3.1. 思路分析3.2. 代码实现 4. 单链表节点的删除4.1. 思路分析4.2. 代码实现 5. 单链表常见面试题5.1.…

影刀sqlite的插入方法

影刀sqlite的插入方法 变量外面不用加‘’

YOLO免费数据集网站收集

目录 Roboflow Universe: Open Source Computer Vision Community Find Open Datasets and Machine Learning Projects | Kaggle ​编辑 【火焰和烟雾图像数据集】-计算机视觉数据集-极市开发者平台 (cvmart.net) 开放数据集- 飞桨AI Studio星河社区 - 人工智能学习与实训社…

【iOS】——知乎日报第五周总结

文章目录 一、评论区展开与收缩二、FMDB库实现本地持久化FMDB常用类&#xff1a;FMDB的简单使用&#xff1a; 三、点赞和收藏的持久化 一、评论区展开与收缩 有的评论没有被回复评论或者被回复评论过短&#xff0c;这时就不需要展开全文的按钮&#xff0c;所以首先计算被回复评…

【LeetCode刷题-树】-- 572.另一棵树的子树

572.另一棵树的子树 方法&#xff1a;深度优先搜索暴力匹配 深度优先搜索枚举root中的每一个节点&#xff0c;判断这个点的子树是否与subroot相等 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right…

电子学会2023年6月青少年软件编程(图形化)等级考试试卷(四级)真题,含答案解析

青少年软件编程(图形化)等级考试试卷(四级) 一、单选题(共10题,共30分) 1. 下列积木运行后的结果是?( )(说明:逗号后面无空格) A.

读书笔记--从一到无穷大的关键金句和阅读感悟

借着休假&#xff0c;重新研读了十多年前读过的乔治.伽莫夫所著图书《从一到无穷大--ONE TWO THREE...INFINITY》&#xff0c;该书作为20世纪最经典的科普类图书之一&#xff0c;当时读的懵懵懂懂&#xff0c;现在重新阅读又有了不同的感受&#xff0c;再结合过去的科研工作&am…

计算机毕业设计选题推荐-内蒙古旅游微信小程序/安卓APP-项目实战

✨作者主页&#xff1a;IT研究室✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…

CBAM注意力机制(结构图加逐行代码注释讲解)

学CBAM前建议先学会SEnet&#xff08;因为本篇涉及SEnet的重合部分会略加带过&#xff09;->传送门 ⒈结构图 下面这个是自绘的&#xff0c;有些许草率。。。 因为CBAM机制是由通道和空间两部分组成的&#xff0c;所以有这两个模块&#xff08;左边是通道注意力机制&#…

【MATLAB】全网唯一的11种信号分解+模糊熵(近似熵)联合算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有18种信号分解算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一算法的代码&#xff0…

【LeetCode刷题-树】--654.最大二叉树

654.最大二叉树 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 1.创建一个根节点&#xff0c;其值为 nums 中的最大值。 2.递归地在最大值 左边 的 子数组前缀上 构建左子树。 3.递归地在最大值 右边 的 子数组后缀上 构建右子树。 返回…

【LeetCode刷题-树】--998.最大二叉树II

998.最大二叉树II /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val val; }* TreeNode(int val, TreeNode left, TreeNode right) {* …

8.1 Windows驱动开发:内核文件读写系列函数

在应用层下的文件操作只需要调用微软应用层下的API函数及C库标准函数即可&#xff0c;而如果在内核中读写文件则应用层的API显然是无法被使用的&#xff0c;内核层需要使用内核专有API&#xff0c;某些应用层下的API只需要增加Zw开头即可在内核中使用&#xff0c;例如本章要讲解…

SQL单表复杂查询where、group by、order by、limit

1.1SQL查询代码如下&#xff1a; select job as 工作类别,count(job) as 人数 from tb_emp where entrydate <2015-01-01 group by job having count(job) > 2 order by count(job) limit 1,1where entrydate <‘2015-01-01’ 表示查询日期小于2015-01-01的记录…

Python大数据之linux学习总结——day11_ZooKeeper

ZooKeeper ZK概述 ZooKeeper概念: Zookeeper是一个分布式协调服务的开源框架。本质上是一个分布式的小文件存储系统 ZooKeeper作用: 主要用来解决分布式集群中应用系统的一致性问题。 ZooKeeper结构: 采用树形层次结构&#xff0c;ZooKeeper树中的每个节点被称为—Znode。且树…

随机过程-张灏

文章目录 导论随机过程相关 学习视频来源&#xff1a;https://www.bilibili.com/video/BV18p4y1u7NP?p1&vd_source5e8340c2f2373cdec3870278aedd8ca4 将持续更新—— 第一次更新&#xff1a;2023-11-19 导论 教材&#xff1a;《随机过程及其应用》陆大絟.张颢 参考&…

X3DAudio1_7.dll丢失原因,X3DAudio1_7.dll丢失怎样解决分享

X3DAudio1_7.dll是一款由微软公司开发的音频处理库&#xff0c;主要用于实现三维音频效果。这个库主要应用于游戏开发、多媒体应用等领域&#xff0c;它可以使得音频更加真实、自然地表现出空间感。如果在使用过程中遇到X3DAudio1_7.dll丢失的问题&#xff0c;可以尝试以下五个…