【C语言教程】【常用类库】(二)字符串处理库 - <string.h>

2. 字符串处理库 - <string.h>

2.1. 基础函数
2.1.1. strlensizeof 区别

strlensizeof 经常被新手混淆,虽然它们看似都能获取长度,但本质上是不同的。

  • strlen:用于获取字符串的实际长度,不包括终止符 \0。该函数从字符串起始位置计数,直到遇到 \0
    • 作用:计算字符串中的字符数。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str[] = "Hello";
          printf("Length of string: %zu\n", strlen(str)); // 输出:5
          return 0;
      }
      
  • sizeof:返回对象所占的内存字节数,包括数组长度(如果是数组)或数据类型大小。
    • 作用:获取内存占用,不限定于字符串。
    • 用法
      #include <stdio.h>
      
      int main() {
          char str[] = "Hello";
          printf("Size of array: %zu\n", sizeof(str)); // 输出:6,因为包括了末尾的 '\0'
          return 0;
      }
      
2.1.2. strcpystrncpy

这两者用于字符串复制,但在处理时有不同的安全考虑。

  • strcpy:复制字符串直到遇到 \0,不进行边界检查,这可能导致缓冲区溢出。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char src[] = "Hello, World!";
          char dst[20];
          strcpy(dst, src);
          printf("Destination: %s\n", dst);
          return 0;
      }
      
  • strncpy:复制最多指定数量的字符,适用于边界需要控制的场合,尤其在需要防止溢出时。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char src[] = "Hello, World!";
          char dst[10];
          strncpy(dst, src, sizeof(dst) - 1);
          dst[9] = '\0'; // 用 '\0' 结束字符串,因为 strncpy 不保证 null-terminated
          printf("Destination: %s\n", dst);
          return 0;
      }
      
2.1.3. strcatstrncat
  • strcat:在目标字符串的结尾追加源字符串,要求目标字符串有足够的空间。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str1[20] = "Hello";
          char str2[] = ", World!";
          strcat(str1, str2);
          printf("Result: %s\n", str1);
          return 0;
      }
      
  • strncat:追加最多指定数量的字符,适用于避免缓冲区溢出。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str1[15] = "Hello";
          char str2[] = ", World!";
          strncat(str1, str2, sizeof(str1) - strlen(str1) - 1);
          printf("Result: %s\n", str1);
          return 0;
      }
      
2.1.4. strcmpstrncmp
  • strcmp:逐字符比较两个字符串,如果相等返回 0,否则返回差值。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str1[] = "Hello";
          char str2[] = "World";
          int result = strcmp(str1, str2);
          printf("Comparison: %d\n", result); // 负值,因为 'H' < 'W'
          return 0;
      }
      
  • strncmp:逐字符比较指定数量的字符,增加了长度控制。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str1[] = "Hello";
          char str2[] = "Hello, World!";
          int result = strncmp(str1, str2, 5); // 比较前5个字符
          printf("Comparison: %d\n", result); // 0,因为相等
          return 0;
      }
      
2.2. 高级函数
2.2.1. strstr 的使用

strstr 用于在一个字符串内查找子串的首次出现。

  • 用法
    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char str[] = "Hello, World!";
        char *substr = strstr(str, "World");
        if (substr) {
            printf("Found substring: %s\n", substr);
        } else {
            printf("Substring not found\n");
        }
        return 0;
    }
    
2.2.2. strtok 的解析

strtok 用于分割字符串,不过注意它的破坏性操作。

  • 用法
    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char str[] = "Hello, World! Welcome to C programming.";
        char *token = strtok(str, " ");
        while (token != NULL) {
            printf("Token: %s\n", token);
            token = strtok(NULL, " ");
        }
        return 0;
    }
    
2.2.3. strspnstrcspn

strspnstrcspn 用于测量字符串的子串结构。

  • strspn:返回字符串中连续出现在另一个字符串中的字符数量。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str[] = "123abc456";
          char keys[] = "1234567890";
          size_t len = strspn(str, keys);
          printf("Initial segment length: %zu\n", len); // 输出:3
          return 0;
      }
      
  • strcspn:返回字符串中不在另一个字符串中出现的字符数量。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str[] = "123abc456";
          char keys[] = "abc";
          size_t len = strcspn(str, keys);
          printf("Initial segment length: %zu\n", len); // 输出:3
          return 0;
      }
      
2.3. 内存操作
2.3.1. memcpymemmove
  • memcpy:拷贝内存区域,源和目标区域不能重叠。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char src[50] = "Hello, World!";
          char dest[50];
          memcpy(dest, src, strlen(src) + 1);
          printf("Destination: %s\n", dest);
          return 0;
      }
      
  • memmove:适合重叠区域的内存拷贝。
    • 用法
      #include <stdio.h>
      #include <string.h>
      
      int main() {
          char str[] = "memmove can be very useful......";
          memmove(str + 20, str + 15, 15);
          printf("%s\n", str); // 输出:memmove can be very very useful
          return 0;
      }
      
2.3.2. memset

memset 用于初始化内存块。

  • 用法
    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char buffer[50];
        memset(buffer, '#', sizeof(buffer)-1);
        buffer[49] = '\0';
        printf("Buffer: %s\n", buffer);
        return 0;
    }
    
2.3.3. memcmp 的比较

memcmp 用于原始内存块的比较。

  • 用法
    #include <stdio.h>
    #include <string.h>
    
    int main() {
        char mem1[] = "abc";
        char mem2[] = "abc";
        int result = memcmp(mem1, mem2, sizeof(mem1));
    
        if (result == 0) {
            printf("Memory blocks are equal.\n");
        } else {
            printf("Memory blocks are different.\n");
        }
        return 0;
    }
    

详细讲解

1. strlen vs sizeof
  • strlen 的应用场景:通常用于获取字符串长度,在字符串操作时确保不会溢出或产生逻辑错误。
  • sizeof 的应用场景:适用于获取数组或数据类型大小,以进行内存管理和缓冲区操作。
2. strcpy vs strncpy
  • strcpy 的危险性:如果目标缓冲区不够大,可能写到未分配的内存,因此在重要场合要避免使用。
  • strncpy 的安全性:加以边界的控制,防止缓冲区溢出,但需要手动处理字符串尾的 \0
3. strcat vs strncat
  • 追加操作:这两个函数用于把一个字符串追加到另一个的末尾。
  • 内存安全strncat 用于确保对目标字符串的追加不超过容量。
4. strcmp vs strncmp
  • 比较用途:两者用于字符串比较,控制比较字符数能提高效率并防止内存访问错误。
5. strstr 使用
  • 在复杂文本处理或者解析场合,strstr 是一个非常有用的工具来检测子串或分割文本。
6. strtok 的解析
  • 注意事项:它会改变源字符串,且多个线程中使用时必须考虑同步问题。
7. strspnstrcspn
  • 应用场景:通常用于解析配置文件、命令行参数时,查找某些前缀或跳过特定字符集。
8. memcpy vs memmove
  • 对于重叠内存区域,必须使用 memmove 以确保正确的内存复制,否则可能得到不可预期的结果。
  • 常用场合:数据结构操作、缓冲区管理、二进制流处理。
9. memset 的用法
  • 初始化内存块是一个经常性的任务,如清空缓存、预分配数据结构。
10. memcmp 的比较
  • 适用于需要直接比较二进制数据块的场合,常用于协议处理、数据校验。

这些函数是 C 语言中处理字符串和内存的基石,其中容易引入错误的地方主要在于边界检查与内存管理。初学者应谨慎使用特别是涉及到动态内存和字符串处理的函数,关注程序的安全和健壮性。

通过对这些函数的深刻理解和精准使用,你将能编写出高效且安全的 C 程序。在实际开发中,建议基于具体应用环境来选择合适的函数,以保证代码的正确性和健壮性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值