C语言:字符函数 & 字符串函数超全总结(用法 + 模拟实现)

在 C 语言编程中,字符与字符串操作是最基础也最频繁的任务之一。标准库提供了一系列强大的函数来处理这些任务,它们主要分为两类:字符函数(处理单个字符)和字符串函数(处理以\0结尾的字符数组)。熟练掌握这些函数的使用和原理,不仅能提升代码效率,还能加深对 C 语言内存管理的理解。


一、字符分类函数

C 语言标准库<ctype.h>中提供了一系列字符分类函数,它们用于判断一个字符(实际是其 ASCII 值)属于哪个类别。这些函数的返回值为非零(真)或零(假)。

常用函数包括:

表格

函数名功能
isalpha判断是否为字母(a-z, A-Z)
isdigit判断是否为十进制数字(0-9)
isalnum判断是否为字母或数字
islower判断是否为小写字母(a-z)
isupper判断是否为大写字母(A-Z)
isspace判断是否为空白字符(空格、换行、制表符等)

使用示例:

#include <stdio.h>
#include <ctype.h>

int main() {
    char ch = 'A';
    if (isalpha(ch)) {
        printf("%c is an alphabet.\n", ch); // 输出: A is an alphabet.
    }
    if (isupper(ch)) {
        printf("%c is an uppercase letter.\n", ch); // 输出: A is an uppercase letter.
    }
    return 0;
}

二、字符转换函数

同样在<ctype.h>中,有两个非常实用的字符转换函数,用于在大小写之间转换。

表格

函数名功能
tolower将大写字母转换为小写
toupper将小写字母转换为大写

注意:如果输入的字符本身不是字母,这两个函数会直接返回原字符。

使用示例:

#include <stdio.h>
#include <ctype.h>

int main() {
    char lower = 'b';
    char upper = 'Y';
    
    printf("%c -> %c\n", lower, toupper(lower)); // 输出: b -> B
    printf("%c -> %c\n", upper, tolower(upper)); // 输出: Y -> y
    
    return 0;
}

三、strlen 的使用和模拟实现

strlen函数用于计算字符串的长度,即从字符串起始地址开始,直到遇到第一个\0为止的字符个数(不包含\0本身)。它声明在<string.h>头文件中。

1. 使用

size_t strlen(const char *str);
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, World!";
    printf("Length: %zu\n", strlen(str)); // 输出: Length: 13
    return 0;
}

2. 模拟实现

我们可以通过指针遍历的方式来模拟实现strlen的功能:

// 方法一:计数器方式
size_t my_strlen1(const char *str) {
    size_t count = 0;
    while (*str != '\0') {
        count++;
        str++;
    }
    return count;
}

// 方法二:递归方式(不创建临时变量)
size_t my_strlen2(const char *str) {
    if (*str == '\0') {
        return 0;
    }
    return 1 + my_strlen2(str + 1);
}

// 方法三:指针-指针方式
size_t my_strlen3(const char *str) {
    const char *start = str;
    while (*str != '\0') {
        str++;
    }
    return str - start;
}

四、strcpy 的使用和模拟实现

strcpy是字符串拷贝函数,用于将一个字符串的内容(包括\0)拷贝到另一个字符数组中。

1. 使用

c

运行

char *strcpy(char *dest, const char *src);

注意事项

  • 源字符串src必须以\0结尾。
  • 目标空间dest必须足够大,以容纳源字符串,否则会导致缓冲区溢出。
  • 目标空间dest必须是可修改的(不能是字符串常量)。
#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello";
    char dest[20] = {0};
    strcpy(dest, src);
    printf("%s\n", dest); // 输出: Hello
    return 0;
}

2. 模拟实现

#include <assert.h>

char *my_strcpy(char *dest, const char *src) {
    // 保存目标字符串的起始地址
    char *ret = dest;
    // 断言指针不为空
    assert(dest != NULL && src != NULL);
    
    // 拷贝内容,直到遇到\0
    while ((*dest++ = *src++)) {
        ;
    }
    return ret;
}

五、strcat 的使用和模拟实现

strcat是字符串追加函数,用于将一个字符串追加到另一个字符串的末尾。

1. 使用

c

运行

char *strcat(char *dest, const char *src);

注意事项

  • 目标字符串dest必须有足够的空间来容纳追加后的总长度。
  • 源字符串src和目标字符串dest都必须以\0结尾。
  • 不能自己追加自己(如strcat(str, str);),这会导致\0被覆盖,函数陷入死循环。

c

运行

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

int main() {
    char str[20] = "Hello";
    strcat(str, " World!");
    printf("%s\n", str); // 输出: Hello World!
    return 0;
}

2. 模拟实现

#include <assert.h>

char *my_strcat(char *dest, const char *src) {
    char *ret = dest;
    assert(dest != NULL && src != NULL);
    
    // 1. 找到dest字符串的末尾\0
    while (*dest) {
        dest++;
    }
    // 2. 从dest的末尾开始拷贝src
    while ((*dest++ = *src++)) {
        ;
    }
    return ret;
}

六、strcmp 的使用和模拟实现

strcmp是字符串比较函数,用于比较两个字符串的内容。它是按字符的 ASCII 值逐位进行比较的。

1. 使用

int strcmp(const char *str1, const char *str2);
  • 如果str1 < str2,返回值小于 0。
  • 如果str1 == str2,返回值等于 0。
  • 如果str1 > str2,返回值大于 0。
#include <stdio.h>
#include <string.h>

int main() {
    printf("%d\n", strcmp("app", "apple")); // 输出: -108 (或其他负数)
    printf("%d\n", strcmp("apple", "app"));  // 输出: 108 (或其他正数)
    printf("%d\n", strcmp("abc", "abc"));    // 输出: 0
    return 0;
}

2. 模拟实现

#include <assert.h>

int my_strcmp(const char *str1, const char *str2) {
    assert(str1 != NULL && str2 != NULL);
    
    while (*str1 == *str2) {
        if (*str1 == '\0') {
            return 0; // 两个字符串完全相等
        }
        str1++;
        str2++;
    }
    // 返回两个字符的差值
    return *str1 - *str2;
}

七、strncpy 函数的使用

strncpystrcpy的 “安全” 版本,它允许指定最多拷贝多少个字符。

c

运行

char *strncpy(char *dest, const char *src, size_t n);
  • src拷贝最多n个字符到dest
  • 如果src的长度小于n,则在拷贝完src后,会用\0填充剩余的n - strlen(src)个字节。
  • 如果src的长度大于或等于n,则dest不会\0结尾!这是一个非常重要的陷阱,使用后必须手动在dest的第n个位置设置\0
#include <stdio.h>
#include <string.h>

int main() {
    char src[] = "Hello, World!";
    char dest[20] = {0};
    
    strncpy(dest, src, 5);
    dest[5] = '\0'; // 手动添加结束符,确保是字符串
    printf("%s\n", dest); // 输出: Hello
    return 0;
}

八、strncat 函数的使用

strncatstrcat的 “安全” 版本,它允许指定最多追加多少个字符。

char *strncat(char *dest, const char *src, size_t n);
  • src追加最多n个字符到dest的末尾。
  • 函数会自动在最终的dest末尾添加一个\0
  • 如果src的长度小于n,则只追加到src\0为止。
#include <stdio.h>
#include <string.h>

int main() {
    char dest[20] = "Hello";
    char src[] = "xxxxWorld!";
    
    strncat(dest, src, 5);
    printf("%s\n", dest); // 输出: HelloxxxxW
    return 0;
}

九、strncmp 函数的使用

strncmpstrcmp的 “限制” 版本,它允许指定最多比较前n个字符。

int strncmp(const char *str1, const char *str2, size_t n);
  • 只比较两个字符串的前n个字符,或者直到出现不同字符 / 遇到\0为止。
#include <stdio.h>
#include <string.h>

int main() {
    printf("%d\n", strncmp("app", "apple", 3)); // 输出: 0 (前3个字符相同)
    printf("%d\n", strncmp("apple", "app", 4)); // 输出: 正数 (第4个字符'l' vs '\0')
    return 0;
}

十、strstr 的使用和模拟实现

strstr是字符串查找函数,用于在一个字符串(haystack)中查找另一个字符串(needle)首次出现的位置。

1. 使用

char *strstr(const char *haystack, const char *needle);
  • 如果找到,返回指向needlehaystack中首次出现位置的指针。
  • 如果未找到,返回NULL
  • 如果needle是空字符串,返回haystack
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "I love C language, C is fun!";
    char substr[] = "C";
    char *pos = strstr(str, substr);
    
    if (pos != NULL) {
        printf("Found at position: %td\n", pos - str); // 输出: Found at position: 7
    }
    return 0;
}

2. 模拟实现

#include <assert.h>

char *my_strstr(const char *haystack, const char *needle) {
    assert(haystack != NULL && needle != NULL);
    
    // 如果子串是空串,直接返回原串
    if (*needle == '\0') {
        return (char *)haystack;
    }
    
    const char *s1, *s2;
    const char *start = haystack;
    
    while (*start) {
        s1 = start;
        s2 = needle;
        
        // 逐个字符比较
        while (*s1 && *s2 && (*s1 == *s2)) {
            s1++;
            s2++;
        }
        
        // 如果s2走到了末尾,说明找到了
        if (*s2 == '\0') {
            return (char *)start;
        }
        
        // 否则,从下一个字符开始重新匹配
        start++;
    }
    
    // 遍历完都没找到
    return NULL;
}

十一、strtok 函数的使用

strtok是字符串分割函数,用于将一个字符串按照指定的分隔符分割成若干个 “令牌”(token)。

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

使用要点

  • 首次调用时,str指向要分割的字符串,delim指向分隔符字符串。
  • 后续调用时,str必须为NULLdelim可以与之前相同或不同。
  • 函数会修改原字符串,将分隔符替换为\0,因此传入的str不能是字符串常量,必须是可修改的字符数组。
  • 函数内部会维护一个静态指针,记录下一次分割的起始位置,因此它不是线程安全的。
#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "a,b,c,d,e";
    char *token = strtok(str, ",");
    
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, ",");
    }
    
    // 输出:
    // a
    // b
    // c
    // d
    // e
    return 0;
}

十二、strerror 函数的使用

strerror函数用于将错误码(errno)转换为对应的可读的错误信息字符串。它声明在<string.h>头文件中。

char *strerror(int errnum);

在 C 标准库中,很多函数在执行失败时会设置全局变量errno的值,strerror可以帮助我们快速定位错误原因。

#include <stdio.h>
#include <string.h>
#include <errno.h> // 必须包含errno.h

int main() {
    FILE *fp = fopen("non_existent_file.txt", "r");
    if (fp == NULL) {
        printf("Error opening file: %s\n", strerror(errno));
        // 输出: Error opening file: No such file or directory
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值