Skip to content

C 标准库 - <string.h>

概述

<string.h> 头文件提供了字符串处理函数,包括字符串复制、连接、比较、搜索、分割等功能。这是 C 语言中最常用的标准库之一。

字符串复制

strcpy()

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

复制字符串。

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

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

strncpy()

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

复制指定长度的字符串。

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

int main() {
    char src[] = "Hello, World!";
    char dest[10];
    
    strncpy(dest, src, 9);
    dest[9] = '\0';
    
    printf("源字符串: %s\n", src);
    printf("目标字符串: %s\n", dest);
    
    return 0;
}

strdup()

c
char *strdup(const char *s);

复制字符串(POSIX)。

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

int main() {
    const char* src = "Hello, World!";
    char* dest = strdup(src);
    
    if (dest != NULL) {
        printf("源字符串: %s\n", src);
        printf("目标字符串: %s\n", dest);
        free(dest);
    }
    
    return 0;
}

字符串连接

strcat()

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

连接字符串。

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

int main() {
    char dest[50] = "Hello, ";
    const char* src = "World!";
    
    strcat(dest, src);
    printf("结果: %s\n", dest);
    
    return 0;
}

strncat()

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

连接指定长度的字符串。

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

int main() {
    char dest[50] = "Hello, ";
    const char* src = "World!";
    
    strncat(dest, src, 5);
    printf("结果: %s\n", dest);
    
    return 0;
}

字符串比较

strcmp()

c
int strcmp(const char *s1, const char *s2);

比较字符串。

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

int main() {
    const char* str1 = "apple";
    const char* str2 = "banana";
    const char* str3 = "apple";
    
    int result1 = strcmp(str1, str2);
    int result2 = strcmp(str1, str3);
    
    printf("strcmp('%s', '%s') = %d\n", str1, str2, result1);
    printf("strcmp('%s', '%s') = %d\n", str1, str3, result2);
    
    return 0;
}

strncmp()

c
int strncmp(const char *s1, const char *s2, size_t n);

比较指定长度的字符串。

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

int main() {
    const char* str1 = "apple pie";
    const char* str2 = "apple cake";
    
    int result = strncmp(str1, str2, 5);
    printf("strncmp('%s', '%s', 5) = %d\n", str1, str2, result);
    
    return 0;
}

strcasecmp()

c
int strcasecmp(const char *s1, const char *s2);

忽略大小写比较字符串(POSIX)。

c
#include <stdio.h>
#include <strings.h>

int main() {
    const char* str1 = "Hello";
    const char* str2 = "HELLO";
    
    int result = strcasecmp(str1, str2);
    printf("strcasecmp('%s', '%s') = %d\n", str1, str2, result);
    
    return 0;
}

字符串长度

strlen()

c
size_t strlen(const char *s);

计算字符串长度。

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

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

字符串搜索

strchr()

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

查找字符首次出现的位置。

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

int main() {
    const char* str = "Hello, World!";
    char c = 'o';
    
    char* result = strchr(str, c);
    
    if (result != NULL) {
        printf("字符 '%c' 首次出现在位置: %ld\n", 
               c, result - str);
    } else {
        printf("未找到字符 '%c'\n", c);
    }
    
    return 0;
}

strrchr()

c
char *strrchr(const char *s, int c);

查找字符最后出现的位置。

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

int main() {
    const char* str = "Hello, World!";
    char c = 'o';
    
    char* result = strrchr(str, c);
    
    if (result != NULL) {
        printf("字符 '%c' 最后出现在位置: %ld\n", 
               c, result - str);
    } else {
        printf("未找到字符 '%c'\n", c);
    }
    
    return 0;
}

strstr()

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

查找子字符串。

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

int main() {
    const char* haystack = "Hello, World!";
    const char* needle = "World";
    
    char* result = strstr(haystack, needle);
    
    if (result != NULL) {
        printf("子字符串 '%s' 出现在位置: %ld\n", 
               needle, result - haystack);
    } else {
        printf("未找到子字符串 '%s'\n", needle);
    }
    
    return 0;
}

字符串分割

strtok()

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

分割字符串。

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

int main() {
    char str[] = "Hello,World,C,Programming";
    const char* delim = ",";
    
    char* token = strtok(str, delim);
    
    printf("分割结果:\n");
    while (token != NULL) {
        printf("  %s\n", token);
        token = strtok(NULL, delim);
    }
    
    return 0;
}

内存操作

memcpy()

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

复制内存块。

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

int main() {
    char src[] = "Hello, World!";
    char dest[20];
    
    memcpy(dest, src, strlen(src) + 1);
    
    printf("源字符串: %s\n", src);
    printf("目标字符串: %s\n", dest);
    
    return 0;
}

memmove()

c
void *memmove(void *dest, const void *src, size_t n);

移动内存块(处理重叠)。

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

int main() {
    char str[] = "Hello, World!";
    
    printf("移动前: %s\n", str);
    memmove(str + 7, str, 5);
    printf("移动后: %s\n", str);
    
    return 0;
}

memcmp()

c
int memcmp(const void *s1, const void *s2, size_t n);

比较内存块。

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

int main() {
    char buf1[] = "Hello";
    char buf2[] = "Hello";
    char buf3[] = "World";
    
    int result1 = memcmp(buf1, buf2, 5);
    int result2 = memcmp(buf1, buf3, 5);
    
    printf("memcmp(buf1, buf2, 5) = %d\n", result1);
    printf("memcmp(buf1, buf3, 5) = %d\n", result2);
    
    return 0;
}

memset()

c
void *memset(void *s, int c, size_t n);

设置内存块。

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

int main() {
    char buffer[20];
    
    memset(buffer, 'A', sizeof(buffer) - 1);
    buffer[sizeof(buffer) - 1] = '\0';
    
    printf("填充后的字符串: %s\n", buffer);
    
    return 0;
}

其他函数

strerror()

c
char *strerror(int errnum);

获取错误代码对应的描述。

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

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

实际应用示例

1. 字符串反转

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

void reverse_string(char* str) {
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++) {
        char temp = str[i];
        str[i] = str[len - i - 1];
        str[len - i - 1] = temp;
    }
}

int main() {
    char str[] = "Hello, World!";
    
    printf("原始字符串: %s\n", str);
    reverse_string(str);
    printf("反转字符串: %s\n", str);
    
    return 0;
}

2. 字符串去空格

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

void trim_whitespace(char* str) {
    int i = 0, j = 0;
    
    while (str[i]) {
        if (!isspace(str[i])) {
            str[j++] = str[i];
        }
        i++;
    }
    str[j] = '\0';
}

int main() {
    char str[] = "  Hello, World!  ";
    
    printf("原始字符串: '%s'\n", str);
    trim_whitespace(str);
    printf("去空格后: '%s'\n", str);
    
    return 0;
}

3. 字符串分割为单词

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

void split_into_words(const char* str) {
    char copy[100];
    strcpy(copy, str);
    
    char* token = strtok(copy, " ");
    
    printf("单词:\n");
    while (token != NULL) {
        printf("  %s\n", token);
        token = strtok(NULL, " ");
    }
}

int main() {
    const char* str = "Hello World C Programming";
    split_into_words(str);
    
    return 0;
}

4. 字符串替换

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

void replace_char(char* str, char old_char, char new_char) {
    for (int i = 0; str[i] != '\0'; i++) {
        if (str[i] == old_char) {
            str[i] = new_char;
        }
    }
}

int main() {
    char str[] = "Hello, World!";
    
    printf("原始字符串: %s\n", str);
    replace_char(str, 'o', 'O');
    printf("替换后: %s\n", str);
    
    return 0;
}

5. 字符串统计

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

typedef struct {
    int letters;
    int digits;
    int spaces;
    int punctuation;
} StringStats;

StringStats analyze_string(const char* str) {
    StringStats stats = {0, 0, 0, 0};
    
    for (int i = 0; str[i] != '\0'; i++) {
        if (isalpha(str[i])) {
            stats.letters++;
        } else if (isdigit(str[i])) {
            stats.digits++;
        } else if (isspace(str[i])) {
            stats.spaces++;
        } else if (ispunct(str[i])) {
            stats.punctuation++;
        }
    }
    
    return stats;
}

int main() {
    const char* str = "Hello, World! 123";
    StringStats stats = analyze_string(str);
    
    printf("字符串: %s\n", str);
    printf("字母: %d\n", stats.letters);
    printf("数字: %d\n", stats.digits);
    printf("空格: %d\n", stats.spaces);
    printf("标点符号: %d\n", stats.punctuation);
    
    return 0;
}

6. 字符串连接

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

char* concat_strings(const char* str1, const char* str2) {
    size_t len1 = strlen(str1);
    size_t len2 = strlen(str2);
    
    char* result = malloc(len1 + len2 + 1);
    if (result == NULL) {
        return NULL;
    }
    
    strcpy(result, str1);
    strcat(result, str2);
    
    return result;
}

int main() {
    const char* str1 = "Hello, ";
    const char* str2 = "World!";
    
    char* result = concat_strings(str1, str2);
    if (result != NULL) {
        printf("连接结果: %s\n", result);
        free(result);
    }
    
    return 0;
}

7. 字符串查找

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

int find_all_occurrences(const char* str, const char* substr) {
    int count = 0;
    const char* ptr = str;
    
    while ((ptr = strstr(ptr, substr)) != NULL) {
        count++;
        ptr++;
    }
    
    return count;
}

int main() {
    const char* str = "Hello, World! Hello, C!";
    const char* substr = "Hello";
    
    int count = find_all_occurrences(str, substr);
    printf("子字符串 '%s' 出现次数: %d\n", substr, count);
    
    return 0;
}

8. 字符串大小写转换

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

void to_uppercase(char* str) {
    for (int i = 0; str[i] != '\0'; i++) {
        str[i] = toupper(str[i]);
    }
}

void to_lowercase(char* str) {
    for (int i = 0; str[i] != '\0'; i++) {
        str[i] = tolower(str[i]);
    }
}

int main() {
    char str1[] = "Hello, World!";
    char str2[] = "Hello, World!";
    
    printf("原始字符串: %s\n", str1);
    to_uppercase(str1);
    printf("大写: %s\n", str1);
    
    to_lowercase(str2);
    printf("小写: %s\n", str2);
    
    return 0;
}

9. 字符串验证

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

int is_valid_email(const char* email) {
    int at_count = 0;
    int dot_count = 0;
    
    for (int i = 0; email[i] != '\0'; i++) {
        if (email[i] == '@') {
            at_count++;
        } else if (email[i] == '.') {
            dot_count++;
        }
    }
    
    return (at_count == 1 && dot_count >= 1);
}

int main() {
    const char* email1 = "user@example.com";
    const char* email2 = "invalid-email";
    
    printf("'%s' 是有效邮箱: %d\n", email1, is_valid_email(email1));
    printf("'%s' 是有效邮箱: %d\n", email2, is_valid_email(email2));
    
    return 0;
}

10. 字符串分割为字符

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

void print_characters(const char* str) {
    printf("字符:\n");
    for (int i = 0; str[i] != '\0'; i++) {
        printf("  [%d] = '%c'\n", i, str[i]);
    }
}

int main() {
    const char* str = "Hello";
    print_characters(str);
    
    return 0;
}

注意事项

1. 缓冲区溢出

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

void good_practice() {
    char src[] = "Hello, World!";
    char dest[20];
    
    strncpy(dest, src, sizeof(dest) - 1);
    dest[sizeof(dest) - 1] = '\0';
    
    printf("%s\n", dest);
}

void bad_practice() {
    char src[] = "Hello, World!";
    char dest[10];
    
    strcpy(dest, src);
    printf("%s\n", dest);
}

2. 字符串终止符

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

void good_practice() {
    char dest[20];
    strncpy(dest, "Hello, World!", 10);
    dest[10] = '\0';
    
    printf("%s\n", dest);
}

void bad_practice() {
    char dest[20];
    strncpy(dest, "Hello, World!", 10);
    
    printf("%s\n", dest);
}

3. 内存重叠

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

void good_practice() {
    char str[] = "Hello, World!";
    memmove(str + 7, str, 5);
    printf("%s\n", str);
}

void bad_practice() {
    char str[] = "Hello, World!";
    memcpy(str + 7, str, 5);
    printf("%s\n", str);
}

4. strtok 的使用

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

void good_practice() {
    char str[] = "Hello,World,C";
    char* token = strtok(str, ",");
    
    while (token != NULL) {
        printf("%s\n", token);
        token = strtok(NULL, ",");
    }
}

void bad_practice() {
    char str[] = "Hello,World,C";
    char* token = strtok(str, ",");
    
    printf("%s\n", token);
    token = strtok(str, ",");
}

总结

<string.h> 提供的字符串处理函数是 C 语言编程的基础:

  1. 功能全面 - 涵盖字符串复制、连接、比较、搜索等
  2. 易于使用 - 提供了简单直观的接口
  3. 广泛应用 - 几乎所有 C 程序都会使用

记住:

  • 注意缓冲区溢出,使用安全的函数
  • 确保字符串正确终止
  • 处理内存重叠时使用 memmove
  • strtok 会修改原字符串
  • 检查函数的返回值