字符串处理是C语言编程中的基础且重要的部分。C标准库提供了一系列强大的字符串处理函数,掌握这些函数能大大提高编程效率。本文将详细介绍这些函数的用法、原理和注意事项。

头文件

所有字符串函数都定义在 <string.h> 头文件中:

#include <string.h>

1. 字符串长度函数

strlen - 计算字符串长度

size_t strlen(const char *str);

功能:返回字符串的长度(不包括结尾的空字符\0

示例

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

int main() {
    char str[] = "Hello World";
    char *ptr = "C Programming";
    
    printf("'%s' 长度: %zu\n", str, strlen(str));     // 11
    printf("'%s' 长度: %zu\n", ptr, strlen(ptr));     // 13
    printf("空字符串长度: %zu\n", strlen(""));         // 0
    
    return 0;
}

手写实现

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

2. 字符串复制函数

strcpy - 字符串复制

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

功能:将src字符串复制到dest,包括结尾的\0

示例

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

int main() {
    char src[] = "Copy this string";
    char dest[20];
    
    strcpy(dest, src);
    printf("源字符串: %s\n", src);
    printf("目标字符串: %s\n", dest);
    
    return 0;
}

手写实现

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

strncpy - 安全字符串复制

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


功能:复制最多n个字符,防止缓冲区溢出

示例:

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

int main() {
    char src[] = "This is a long string";
    char dest[10];
    
    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0';  // 手动添加结束符
    
    printf("安全复制: %s\n", dest);
    
    return 0;
}

3. 字符串连接函数

strcat - 字符串连接

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

功能:将src字符串连接到dest末尾

示例

include <string.h>

int main() {
    char str1[20] = "Hello";
    char str2[] = " World";
    
    strcat(str1, str2);
    printf("连接结果: %s\n", str1);  // "Hello World"
    
    return 0;
}

手写实现

char *my_strcat(char *dest, const char *src) {
    char *start = dest;
    
    // 找到dest的结尾
    while (*dest != '\0') {
        dest++;
    }
    
    // 复制src到dest末尾
    while ((*dest = *src) != '\0') {
        dest++;
        src++;
    }
    
    return start;
}

strncat - 安全字符串连接

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

4. 字符串比较函数

strcmp - 字符串比较

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

返回值

  • <0:str1 < str2

  • =0:str1 == str2

  • >0:str1 > str2

示例

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

int main() {
    char str1[] = "apple";
    char str2[] = "banana";
    char str3[] = "apple";
    
    // 比较不同字符串
    printf("apple vs banana: %d\n", strcmp(str1, str2));  // 返回负值
    printf("banana vs apple: %d\n", strcmp(str2, str1));  // 返回正值
    printf("apple vs apple: %d\n", strcmp(str1, str3));   // 返回0
    
    return 0;
}
 

手写实现

int my_strcmp(const char *str1, const char *str2) {
    while (*str1 && *str1 == *str2) {
        ++str1;
        ++str2;
    }
    return *(unsigned char*)str1 - *(unsigned char*)str2;
}
 

strncmp - 比较前n个字符

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

5. 字符串查找函数

strchr - 查找字符第一次出现

char *strchr(const char *str, int c);

示例

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

int main() {
    char str[] = "Hello World";
    char *result;
    
    result = strchr(str, 'o');
    if (result != NULL) {
        printf("找到 'o',位置: %ld,后续字符串: %s\n", 
               result - str, result);  // 位置: 4, 字符串: "o World"
    }
    
    result = strchr(str, 'x');
    if (result == NULL) {
        printf("未找到 'x'\n");
    }
    
    return 0;
}

strstr - 查找子字符串

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

示例

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

int main() {
    char text[] = "C programming is fun";
    char *found;
    
    found = strstr(text, "program");
    if (found != NULL) {
        printf("找到子串,位置: %ld,内容: %s\n", 
               found - text, found);  // "programming is fun"
    }
    
    return 0;
}

6. 字符串分割函数


strtok - 字符串分割

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


示例:

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

int main() {
    char text[] = "apple,banana,cherry,date";
    char *token;
    
    printf("原始字符串: %s\n", text);
    printf("分割结果:\n");
    
    // 第一次调用
    token = strtok(text, ",");
    while (token != NULL) {
        printf("- %s\n", token);
        token = strtok(NULL, ",");  // 后续调用传NULL
    }
    
    return 0;
}

7. 内存操作函数


memcpy - 内存复制

void *memcpy(void *dest, const void *src, size_t n);


示例:

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

int main() 
{
    int src[] = {1, 2, 3, 4, 5};
    int dest[5];
    
    memcpy(dest, src, sizeof(src));
    
    printf("复制结果: ");
    for (int i = 0; i < 5; i++) {
        printf("%d ", dest[i]);  // 1 2 3 4 5
    }
    printf("\n");
    
    return 0;
}


memset - 内存设置

void *memset(void *ptr, int value, size_t n);


示例:

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

int main() {
    char buffer[10];
    
    // 初始化为0
    memset(buffer, 0, sizeof(buffer));
    
    // 设置为特定值
    memset(buffer, 'A', 5);
    buffer[5] = '\0';
    
    printf("结果: %s\n", buffer);  // "AAAAA"
    
    return 0;
}

综合应用示例

示例1:字符串处理工具函数

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

// 去除字符串末尾的换行符
void trim_newline(char *str) {
    int len = strlen(str);
    if (len > 0 && str[len - 1] == '\n') {
        str[len - 1] = '\0';
    }
}

// 字符串反转
void reverse_string(char *str) {
    int len = strlen(str);
    for (int i = 0, j = len - 1; i < j; i++, j--) {
        char temp = str[i];
        str[i] = str[j];
        str[j] = temp;
    }
}

int main() {
    char text[100];
    
    printf("输入字符串: ");
    fgets(text, sizeof(text), stdin);
    trim_newline(text);
    
    printf("原始: %s\n", text);
    printf("长度: %zu\n", strlen(text));
    
    reverse_string(text);
    printf("反转: %s\n", text);
    
    return 0;
}

示例2:安全字符串操作

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

void safe_string_operations() {
    char buffer[20];
    const char *source = "This is a very long string that might cause overflow";
    
    // 安全复制
    strncpy(buffer, source, sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';
    
    printf("安全复制: %s\n", buffer);
    
    // 安全连接
    char base[30] = "Hello";
    const char *to_append = " World and everyone";
    
    strncat(base, to_append, sizeof(base) - strlen(base) - 1);
    printf("安全连接: %s\n", base);
}

int main() {
    safe_string_operations();
    return 0;
}

常见错误与注意事项

错误1:缓冲区溢出

// 错误示例
char dest[5];
char src[] = "This is too long";
strcpy(dest, src);  // 缓冲区溢出!

// 正确做法
strncpy(dest, src, sizeof(dest) - 1);
dest[sizeof(dest) - 1] = '\0';

错误2:未检查返回值

// 错误示例
char *result = strchr(str, 'a');
printf("找到: %s\n", result);  // 如果result为NULL会崩溃

// 正确做法
char *result = strchr(str, 'a');
if (result != NULL) {
    printf("找到: %s\n", result);
} else {
    printf("未找到\n");
}

错误3:修改字符串常量

// 错误示例
char *str = "constant string";
str[0] = 'X';  // 未定义行为!

// 正确做法
char str[] = "modifiable string";
str[0] = 'X';  // 正确

性能优化技巧

  1. 避免重复计算长度:

    // 不好
    for (int i = 0; i < strlen(str); i++) { ... }
    
    // 好
    int len = strlen(str);
    for (int i = 0; i < len; i++) { ... }
  2. 使用memcpy处理大数据

    // 对于大型数据块,memcpy比strcpy更快
    memcpy(dest, src, size);

  3. 合理使用栈和堆

    // 小字符串用栈
    char stack_str[100];
    
    // 大字符串或动态长度用堆
    char *heap_str = malloc(required_size);

总结

C语言的字符串函数虽然基础,但功能强大。掌握这些函数的关键点:

  • ✅ 理解每个函数的参数和返回值

  • ✅ 注意缓冲区安全和边界检查

  • ✅ 区分字符串常量和可修改字符串

  • ✅ 合理选择函数(strcpy vs strncpy等)

  • ✅ 正确处理NULL指针和错误情况

通过熟练运用这些函数,你可以高效地处理各种字符串操作任务,写出更安全、更健壮的C语言程序。

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐