24 C 语言常用的字符串处理函数详解:strlen、strcat、strcpy、strcmp、strchr、strrchr、strstr、strtok

发布于:2024-10-12 ⋅ 阅读:(8) ⋅ 点赞:(0)

目录

1 strlen

1.1 函数原型

1.2 功能说明

1.3 案例演示

1.4 注意事项

2 strcat

2.1 函数原型

2.2 功能说明

2.3 案例演示

2.4 注意事项

3 strcpy

3.1 函数原型

3.2 功能说明

3.3 案例演示

3.4 注意事项

4 strcmp

4.1 函数原型

4.2 功能说明

4.3 案例演示

4.4 注意事项

5 strchr

5.1 函数原型

5.2 功能说明

5.3 案例演示

5.4 注意事项

6 strrchr

6.1  函数原型

6.2 功能说明

6.3 案例演示

6.4 注意事项

7 strstr

7.1 函数原型

7.2 功能说明

7.3 案例演示

7.4 注意事项

8 strtok

8.1 函数原型

8.2 功能说明

8.3 案例演示

8.4 注意事项

9 总结对比表


1 strlen

1.1 函数原型

        strlen 函数是 C 语言标准库中的一个函数,用于计算字符串的长度(不包括终止的空字符 '\0')。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
size_t strlen(const char *str);
  • 参数:const char *str指向以 null 结尾的字符串的指针
  • 返回值:size_t表示字符串的长度,即不包括终止的空字符 '\0' 的字符数。最好使用 %zu 进行打印输出。

1.2 功能说明

        strlen 函数遍历传入的字符串,直到遇到第一个空字符 '\0' 为止,并返回遍历过程中遇到的字符数(不包括 '\0')。这个函数对于处理 C 语言中的字符串非常有用,因为 C 语言中的字符串是以空字符 '\0' 结尾的字符数组

1.3 案例演示

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

int main()
{
    char str[] = "Hello,World!";
    printf("字符串 '%s' 的长度是:%zu,sizeof(str)=%zu\n", str, strlen(str), sizeof(str));

    // 演示空字符串的情况
    char emptyStr[] = "";
    printf("空字符串 '%s' 的长度是:%zu,sizeof(emptyStr)=%zu\n", emptyStr, strlen(emptyStr), sizeof(emptyStr));

    // 演示包含空格的字符串
    char spaceStr[] = "Hello World";
    printf("包含空格的字符串 '%s' 的长度是:%zu,sizeof(spaceStr)=%zu\n", spaceStr, strlen(spaceStr), sizeof(spaceStr));

    return 0;
}

        输出结果如下所示:

1.4 注意事项

        不包含终止符strlen 返回的长度不包括字符串末尾的空字符 '\0'

        参数检查:使用 strlen 时,应确保传入的指针不是 NULL,否则会导致未定义行为(通常是程序崩溃)。

        性能考虑:由于 strlen 需要遍历整个字符串直到找到 '\0',因此其性能与字符串的长度成正比。在处理非常长的字符串时,应考虑性能影响。

        修改字符串:虽然 strlen 的参数是 const char *,意味着理论上不应修改字符串,但在实际编程中,确保在调用 strlen 后不修改字符串,因为后续操作可能依赖于字符串的原始内容。

        替代方案:在某些情况下,如果已知字符串的最大长度,或者字符串存储在固定大小的数组中,可以考虑使用数组的大小作为长度,而不是调用 strlen。这可以避免运行时开销,并可能提高性能。

        安全性:在处理来自不可信源的字符串时,应确保字符串不会超出预期的长度,以避免缓冲区溢出等安全问题。


2 strcat

2.1 函数原型

        strcat 函数是 C 语言标准库中的一个函数,用于将两个字符串连接起来。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
char *strcat(char *dest, const char *src);
  • 参数:
    • char *dest:指向目标字符串的指针,即要连接到的字符串。这个字符串必须有足够的空间来存储两个字符串连接后的结果
    • const char *src:指向源字符串的指针,即要连接到目标字符串末尾的字符串
  • 返回值:返回指向目标字符串(dest)的指针

2.2 功能说明

        strcat 函数将 src 字符串(终止的空字符 '\0' 之前的所有字符)追加到 dest 字符串的末尾(原来存放 '\0' 的位置),并自动在结果字符串的末尾添加一个新的空字符 '\0'如果 dest 和 src 指向的字符串重叠,则行为是未定义的

2.3 案例演示

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

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

    // 使用 strcat 连接字符串
    strcat(dest, src);

    // 输出连接后的字符串
    printf("连接后的字符串是:%s\n", dest);

    return 0;
}

        输出结果如下所示:

        字符串初始化完成后的存储情况,如下所示:

        使用 strcat 追加字符串后,目标字符串内容如下所示:

2.4 注意事项

        空间足够确保目标字符串 dest 有足够的空间来存储两个字符串连接后的结果,包括额外的终止空字符 '\0'。如果空间不足,将导致缓冲区溢出,这是常见的安全问题。

        重叠字符串如果 dest 和 src 指向的字符串内存区域重叠,则 strcat 的行为是未定义的。在这种情况下,应使用 strncat 或其他安全的字符串处理函数。

        空字符串如果 src 是空字符串(即仅包含 '\0'),则 dest 字符串不会改变,但函数仍然会返回 dest 的指针。

        返回值:虽然 strcat 的返回值通常不是必需的,但了解它返回的是 dest 的指针可以在某些情况下简化代码。

        安全性:在处理来自不可信源的字符串时,应特别小心,以避免缓冲区溢出等安全问题。考虑使用 strncat 或其他更安全的字符串处理函数。

        终止符strcat 会自动在连接后的字符串末尾添加一个新的终止空字符 '\0'。这是确保字符串正确结束的关键。

        性能:strcat 需要遍历 dest 字符串以找到其末尾的空字符,然后才能开始追加 src 字符串。因此,其性能与 dest 字符串的长度成正比。在处理非常长的字符串时,应考虑性能影响。


3 strcpy

3.1 函数原型

        strcpy 函数是 C 语言标准库中的一个函数,用于复制字符串。它的函数原型定义在 <string.h> 头文件中。

#include <string.h>  
char *strcpy(char *dest, const char *src);
  • 参数:
    • dest:目标字符串的指针,即要复制到的字符串的起始地址。
    • src:源字符串的指针,即要复制的字符串的起始地址。
  • 返回值:函数返回 dest 的指针

3.2 功能说明

        strcpy 函数将 src 指向的字符串复制到 dest 指向的数组中,包括终止的空字符('\0')。因此,dest 指向的数组必须足够大,以容纳要复制的字符串,包括终止的空字符。如果 dest 和 src 重叠,则 strcpy 的行为是未定义的

        strcpy 函数的工作原理是从源字符串的第一个字符开始,逐个字符地复制到目标字符串数组中,直到遇到源字符串的终止空字符('\0')为止。在这个过程中,目标字符串数组中从起始位置到终止空字符之前的所有内容都会被源字符串的内容所替换

        如果目标字符串数组之前已经包含了一些内容,并且这些内容的长度大于或等于源字符串的长度(不包括终止空字符),那么只有在目标字符串数组中与源字符串对应位置上的内容会被覆盖;如果目标字符串数组之前的内容长度小于源字符串的长度,那么除了被覆盖的部分外,源字符串中剩余的部分(包括终止空字符)也会被追加到目标字符串数组的末尾,但这通常不是 strcpy 的预期用法,因为它可能会导致缓冲区溢出。然而,在实际应用中,我们通常会确保目标字符串数组有足够的空间来存储源字符串的内容(包括终止空字符),并且我们确实希望用源字符串的内容来替换目标字符串数组中的内容。

3.3 案例演示

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

int main()
{
    char dest[50]; // 目标字符串,确保有足够的空间来存放复制的字符串
    char src[] = "Hello, World!"; // 源字符串
    printf("dest 字符数组一开始是垃圾值!\n");
    // 使用 strcpy 函数复制字符串
    strcpy(dest, src);
    // 输出复制的字符串
    printf("dest 字符数组复制源字符串 src(包括空字符)后的内容为: %s\n", dest);

    char src2[] = "111111";
    // 如果目标字符串一开始有数据,复制之后会导致原始数据被完全覆盖
    char dest2[] = "22222222222";
    printf("dest2 字符数组原来的字符串为: %s\n", dest2);
    // 使用 strcpy 函数复制字符串
    strcpy(dest2, src2);
    // 输出复制的字符串
    printf("dest2 字符数组复制源字符串 src2(包括空字符)后的内容为:%s\n", dest2);

    return 0;
}

        输出结果如下所示:

        字符数组 dest2 原始数据的存储情况,如下所示:

        执行 strcpy(dest2, src2);  后 desc2 中的值,如下所示:

 3.4 注意事项

        缓冲区溢出如果目标数组 dest 的大小不足以容纳源字符串 src(包括终止的空字符),则会发生缓冲区溢出,这可能导致未定义的行为,包括程序崩溃或安全漏洞。

        重叠内存如果 dest 和 src 指向的内存区域重叠,则 strcpy 的行为是未定义的。在这种情况下,应使用 memmove 函数,它总是安全地处理重叠内存。

        字符串终止strcpy 会复制源字符串中的终止空字符('\0'),因此目标字符串也会被正确地终止。

        覆盖原有内容如果目标字符串数组之前已经包含了一些内容,并且这些内容的长度大于或等于源字符串的长度(不包括终止空字符),那么只有在目标字符串数组中与源字符串对应位置上的内容会被覆盖

        返回值:虽然 strcpy 的返回值(dest 的指针)在大多数情况下不是必需的,但它可以用于链式调用或错误检查(尽管对于 strcpy 来说,错误检查通常是通过确保目标缓冲区足够大来实现的)。

        安全性:由于 strcpy 不检查目标缓冲区的大小,因此建议使用更安全的字符串复制函数,如 strncpy(尽管 strncpy 有其自己的限制和注意事项)。对于需要安全复制字符串的场景,考虑使用 strlcpy(如果可用)或手动实现一个安全的复制函数。 


4 strcmp

4.1 函数原型

        strcmp 函数是 C 语言标准库中的一个函数,用于比较两个字符串。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
int strcmp(const char *str1, const char *str2);
  • 参数:
    • const char *str1:指向第一个要比较的字符串的指针。
    • const char *str2:指向第二个要比较的字符串的指针。
  • 返回值:
    • 如果 str1 和 str2 字符串相等,则返回 0
    • 如果 str1 在字典序(基于字符的 ASCII 值)上小于 str2,则返回一个小于 0 的值
    • 如果 str1 在字典序(基于字符的 ASCII 值)上大于 str2,则返回一个大于 0 的值

4.2 功能说明

        strcmp 函数逐个字符地比较两个字符串,直到出现不同的字符或遇到字符串的终止符 '\0'。如果两个字符串在所有对应位置上的字符都相同,则认为这两个字符串相等。如果在某个位置上,str1 的字符在 ASCII 码表中小于 str2 的对应字符,则认为 str1 在字典序上小于 str2;反之亦然。

4.3 案例演示

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

int main()
{
    char str1[] = "Hello";
    char str2[] = "World";
    char str3[] = "Hello";

    // 比较 str1 和 str2
    int result1 = strcmp(str1, str2);
    if (result1 < 0)
    {
        printf("'%s' 在字典序上小于 '%s'\n", str1, str2);
    }
    else if (result1 > 0)
    {
        printf("'%s' 在字典序上大于 '%s'\n", str1, str2);
    }
    else
    {
        printf("'%s' 和 '%s' 相等\n", str1, str2);
    }

    // 比较 str1 和 str3
    int result2 = strcmp(str1, str3);
    if (result2 == 0)
    {
        printf("'%s' 和 '%s' 相等\n", str1, str3);
    }

    return 0;
}

        输出结果如下所示:

4.4 注意事项

        大小写敏感strcmp 函数是大小写敏感的,即 'A' 和 'a' 被视为不同的字符

        空字符串:如果任一字符串为空(即仅包含终止符 '\0',ASCII 值是 0),则非空字符串在字典序上大于空字符串

        未定义行为:如果任一指针为 NULL,则 strcmp 的行为是未定义的。在实际使用中,应确保传入的指针是有效的。

        返回值的使用:虽然返回值可以用于判断两个字符串的相对大小,但直接比较返回值与 0、<0 或 >0 时应小心,因为具体的返回值(除了 0 之外)是未指定的,并且可能因实现而异

        安全性:strcmp 本身不涉及内存分配或修改字符串内容,因此从安全性的角度来看,它相对安全。然而,在使用 strcmp 时仍需注意确保传入的字符串指针是有效的,并且不会越界访问内存。 


5 strchr

5.1 函数原型

        strchr 函数是 C 语言标准库中的一个函数,用于在字符串中查找第一次出现的指定字符。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
char *strchr(const char *str, int c);
  • 参数:
    • const char *str:指向要搜索的字符串的指针。
    • int c要搜索的字符(以 int 形式传递,以便可以传递 EOF 等特殊值,但通常传递字符的 ASCII 值)。
  • 返回值:
    • 如果找到字符 c,则返回指向该字符在字符串中第一次出现的位置的指针
    • 如果未找到字符 c,则返回 NULL

5.2 功能说明

        strchr 函数遍历字符串 str,查找字符 c 的第一次出现。如果找到该字符,函数将返回一个指向该字符的指针;如果未找到,则返回 NULL。注意,搜索是区分大小写的

5.3 案例演示

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

int main()
{
    char str[] = "Hello, World!";
    char *pos;

    // 查找字符 'o'
    pos = strchr(str, 'o');
    if (pos != NULL)
    {
        printf("找到字符 'o',位置:%d\n", pos - str + 1); // 输出位置(基于 1 的索引)
    }
    else
    {
        printf("未找到字符 'o'。\n");
    }

    // 查找字符 'W'(注意大小写)
    pos = strchr(str, 'W');
    if (pos != NULL)
    {
        printf("找到字符 'W',位置:%d\n", pos - str + 1); // 输出位置(基于 1 的索引)
    }
    else
    {
        printf("未找到字符 'W'。\n");
    }

    // 查找不存在的字符
    pos = strchr(str, 'x');
    if (pos == NULL)
    {
        printf("未找到字符 'x'。\n");
    }

    return 0;
}

        输出结果如下所示:

5.4 注意事项

        大小写敏感strchr 函数在搜索时是区分大小写的

        返回值类型:尽管 strchr 的参数是 const char *,但返回类型是 char *。这允许调用者通过返回的指针修改字符串(尽管修改原始字符串指针指向的内容可能不是个好主意,因为它可能违反了原始数据的不可变性假设)。然而,如果原始字符串是字面量或位于只读内存区域,尝试修改返回的字符串可能会导致未定义行为。

        空字符串和 NULL 指针:如果 str 是空字符串(即仅包含终止的 '\0'),则 strchr 仅在未搜索到字符时返回 NULL。如果 str 是 NULL,则 strchr 的行为是未定义的,因此在调用之前应确保 str 不是 NULL

        字符参数尽管 strchr 的第二个参数是 int 类型,但通常传递的是字符的 ASCII 值或字符常量。这允许传递 EOF 或其他特殊值,但在搜索字符串字符时并不常用

        效率:strchr 函数通常实现为线性搜索,即从头开始逐个字符地检查字符串,直到找到指定的字符或到达字符串的末尾。因此,在最坏的情况下,其时间复杂度为 O(n),其中 n 是字符串的长度。


6 strrchr

6.1  函数原型

        strrchr 函数是 C 语言标准库中的一个函数,用于在字符串中查找最后一次出现的指定字符。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
char *strrchr(const char *str, int c);
  • 参数:
    • const char *str:指向要搜索的字符串的指针。
    • int c:要搜索的字符(以 int 形式传递,但通常传递的是字符的 ASCII 值)。
  • 返回值:
    • 如果找到字符 c,则返回指向该字符在字符串中最后一次出现的位置的指针。
    • 如果未找到字符 c,则返回 NULL

6.2 功能说明

        strrchr 函数遍历字符串 str,从字符串的末尾开始向前搜索,查找字符 c 的最后一次出现。如果找到该字符,函数将返回一个指向该字符的指针;如果未找到,则返回 NULL。注意,搜索是区分大小写的

6.3 案例演示

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

int main()
{
    char str[] = "Hello, World! This is a test.";
    char *pos;

    // 查找字符 'o'
    pos = strrchr(str, 'o');
    if (pos != NULL)
    {
        printf("找到字符 'o',最后一次出现的位置:%d\n", pos - str + 1); // 输出位置(基于 1 的索引)
    }
    else
    {
        printf("未找到字符 'o'。\n");
    }

    // 查找字符 't'(注意字符串中有多个't')
    pos = strrchr(str, 't');
    if (pos != NULL)
    {
        printf("找到字符 't',最后一次出现的位置:%d\n", pos - str + 1); // 输出位置(基于 1 的索引)
    }
    else
    {
        printf("未找到字符 't'。\n");
    }

    // 查找不存在的字符
    pos = strrchr(str, 'x');
    if (pos == NULL)
    {
        printf("未找到字符 'x'。\n");
    }

    return 0;
}

        输出结果如下所示:

6.4 注意事项

        大小写敏感strrchr 函数在搜索时是区分大小写的

        返回值类型:尽管 strrchr 的参数是 const char *,但返回类型是 char *。这允许调用者通过返回的指针修改字符串(尽管这可能不是个好主意,特别是如果原始字符串是字面量或位于只读内存区域)。

        空字符串和 NULL 指针:如果 str 是空字符串(即仅包含终止的 '\0'),则 strrchr 仅在未搜索到字符时返回 NULL。如果 str 是 NULL,则 strrchr 的行为是未定义的,因此调用前必须确保 str 不是 NULL

        字符参数:尽管 strrchr 的第二个参数是 int 类型,但通常传递的是字符的 ASCII 值或字符常量。

        效率:与 strchr 类似,strrchr 函数通常实现为从字符串末尾开始的线性搜索,其时间复杂度在最坏情况下为 O(n),其中 n 是字符串的长度。然而,由于它从末尾开始搜索,对于某些特定情况(如查找字符串末尾的特定字符),它可能比从头开始的搜索更高效。


7 strstr

7.1 函数原型

        strstr 函数是 C 语言标准库中的一个函数,用于在字符串中查找第一次出现的子串。其函数原型定义在 <string.h> 头文件中。

#include <string.h>  
char *strstr(const char *str1, const char *str2);
  • 参数:
    • const char *str1:指向要搜索的字符串(主字符串)的指针
    • const char *str2:指向要搜索的子串的指针
  • 返回值:
    • 如果找到子串 str2,则返回指向 str1 中子串 str2 第一次出现的位置的指针
    • 如果未找到子串 str2,则返回 NULL

7.2 功能说明

        strstr 函数遍历字符串 str1,查找第一次出现的与 str2 完全相同的子串。如果找到这样的子串,函数将返回一个指向 str1 中该子串起始位置的指针;如果未找到,则返回 NULL。搜索是区分大小写的

  • 如果 str2 是空字符串(即仅包含终止的 '\0'),则 strstr 将返回 str1 的起始地址,因为空字符串是任何字符串的子串
  • 如果 str1 或 str2 是 NULL,则 strstr 的行为是未定义的,因此在调用之前应确保这两个参数都不是 NULL。

7.3 案例演示

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

int main()
{
    char str1[] = "Hello, World! This is a test.";
    char str2[] = "World";
    char *pos;

    // 查找子串 "World"
    pos = strstr(str1, str2);
    if (pos != NULL)
    {
        printf("找到子串 '%s',位置:%d\n", str2, pos - str1 + 1); // 输出位置(基于 1 的索引)
    }
    else
    {
        printf("未找到子串 '%s'。\n", str2);
    }

    // 查找不存在的子串
    char str3[] = "xyz";
    pos = strstr(str1, str3);
    if (pos == NULL)
    {
        printf("未找到子串 '%s'。\n", str3);
    }

    // 查找空子串(虽然不常见,但技术上可行)
    char str4[] = "";
    pos = strstr(str1, str4);
    if (pos != NULL)
    {
        printf("找到空子串,位置:%d(即字符串开头)\n", pos - str1 + 1); // 输出位置(基于 1 的索引)
    }

    return 0;
}

        输出结果如下所示:

7.4 注意事项

        大小写敏感strstr 函数在搜索时是区分大小写的

        返回值类型:尽管 strstr 的参数是 const char *,但返回类型是 char *。这允许调用者通过返回的指针访问或修改子串(但请注意,如果原始字符串是字面量或位于只读内存区域,则不应修改它)。然而,修改返回的字符串可能会影响原始字符串的其余部分,因为它们是连续存储的。

        空字符串和 NULL 指针如果 str2 是空字符串(即仅包含终止的 '\0'),则 strstr 将返回 str1 的起始地址,因为空字符串是任何字符串的子串如果 str1 或 str2 是 NULL,则 strstr 的行为是未定义的,因此在调用之前应确保这两个参数都不是 NULL。

        效率:strstr 函数的实现通常涉及两个字符串的逐字符比较,直到找到匹配的子串或遍历完 str1。在最坏的情况下,其时间复杂度为 O(n*m),其中 n 是 str1 的长度,m 是 str2 的长度。然而,对于许多实际应用,由于 str2 通常较短,因此效率是可以接受的。

        重叠字符串:如果 str2 是 str1 的一个后缀,并且两个字符串在内存中是重叠的(尽管这种情况在标准 C 字符串操作中不常见),则 strstr 仍然能够正确找到子串。但是,在修改返回的字符串时要特别小心,以避免破坏原始字符串的其余部分。


8 strtok

8.1 函数原型

        strtok 函数是 C 语言标准库中的一个函数,用于分割字符串为一系列标记(tokens)。其函数原型定义在 <string.h> 头文件中,并需要一个额外的 <stdlib.h> 头文件来访问 NULL(在某些实现中可能不是必需的,但出于清晰和可移植性考虑,建议包含)。

#include <string.h>  
// 可能还需要 #include <stdlib.h>,尽管在函数原型中未直接使用  
char *strtok(char *str, const char *delim);
  • 参数:
    • char *str:指向要分割的字符串的指针在首次调用时,它应该是一个指向要分割的字符串的指针。在后续的调用中,它应该是 NULL,以便 strtok 继续从上次停止的地方开始分割
    • const char *delim:指向一个字符串,包含用作分隔符的字符集合
  • 返回值:返回指向下一个标记的指针。如果没有更多的标记,则返回 NULL

8.2 功能说明

        strtok 函数通过扫描 str 指向的字符串来查找由 delim 字符串中任一字符分隔的标记(token)找到的第一个标记由函数返回,并在原始字符串中用 \0 替换分隔符在后续的调用中,通过将 str 设置为 NULL,strtok 会继续从上次停止的地方扫描剩余的字符串

        strtok 函数在字符串中遇到连续的分隔符时,它会将这些连续的分隔符都视为单个分隔符,并在结果中忽略它们(即不会将连续分隔符视为多个分隔符来产生多个空标记)。

8.3 案例演示

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

int main()
{
    char str[] = "Hello, World! This is a test.";
    const char delimiters[] = " ,.!";

    // 返回指向下一个标记的指针。如果没有更多的标记,则返回 NULL
    char *token;

    // 获取第一个标记
    token = strtok(str, delimiters);
    while (token != NULL)
    {
        printf("标记:%s\n", token);

        // 获取下一个标记
        token = strtok(NULL, delimiters);
    }

    // 注意:此时 str 已被 strtok 修改,分隔符被替换为 '\0'
    // 如果需要原始字符串,应保留一份副本

    return 0;
}

        输出结果如下所示:

        字符串初始化完成后的存储情况,如下所示:

        使用 strtok 分割字符串后,分隔符被替换为 '\0',源字符串内容如下所示:

        如果两个标记之间只有分隔符(没有非分隔符字符),那么 strtok 会在遇到第一个分隔符时停止,并返回当前的标记。然而,在紧接着的下一次调用中(仍然传递 NULL),由于所有分隔符都已被跳过,并且没有找到新的非分隔符字符来开始新的标记,strtok 将返回 NULL,表示没有更多的标记可供读取。

        例如,在上述代码中,World 和 This 之间有一个感叹号和一个空格作为分隔符,但 strtok 不会为这些分隔符都生成空标记。它只会将它们视为分隔 World 和 This 这两个标记的边界。因此,strtok 会返回 "Hello" 作为第一个标记,然后是 "World",接着是 "This",依此类推,直到字符串结束。 

8.4 注意事项

        修改原始字符串strtok 会修改传入的字符串,用 \0 替换分隔符。如果需要保留原始字符串,请在使用 strtok 之前创建一份副本。

        线程安全性:strtok 不是线程安全的,因为它使用静态变量来存储对原始字符串的引用和上次分割的位置。在多线程环境中,如果需要同时分割多个字符串,应考虑使用 strtok_r(在 POSIX 兼容系统中可用),它是 strtok 的可重入版本。

        分隔符字符串分隔符字符串中的字符可以是任何字符,包括空格、标点符号等。但是,要注意分隔符字符串中的字符是逐个检查的,而不是作为整体字符串来搜索

        连续分隔符如果字符串中有连续的分隔符,strtok 会将它们视为单个分隔符,并跳过它们,只返回一个空标记(如果请求的话)。如果两个标记之间只有分隔符,则在这些分隔符之后调用 strtok 时会立即返回 NULL,因为没有更多的标记可以读取

        空字符串如果 str 是一个空字符串,strtok 将立即返回 NULL,因为没有标记可以提取

        NULL 参数在首次调用 strtok 之后,必须通过将 str 设置为 NULL 来继续分割操作,而不是再次传递原始字符串的指针。


9 总结对比表

函数名称 函数原型 功能描述 关键点
strlen

#include <string.h>

size_t strlen(const char *str);

计算字符串 str 的长度,不包括终止的空字符 \0。 返回值类型是 size_t(%zu 打印输出),表示无符号整数。
strcat

#include <string.h>

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

将 src 字符串追加到 dest 字符串的末尾,并在结果字符串的末尾添加一个空字符 \0。 dest 必须有足够的空间来容纳结果字符串。如果 dest 和 src 重叠,行为未定义。
strcpy

#include <string.h>  

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

将 src 字符串复制到 dest,包括终止的空字符 \0。 dest 必须有足够的空间来容纳 src 字符串。如果 dest 和 src 重叠,行为未定义。
strcmp

#include <string.h>

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

比较两个字符串 str1 和 str2。 返回值:如果 str1 和 str2 相等,返回 0;如果 str1 小于 str2,返回负数;如果 str1 大于 str2,返回正数。
strchr

#include <string.h>

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

查找字符串 str 中第一次出现的字符 c,并返回该字符的指针。如果未找到,则返回 NULL。 c 是一个整数,可以是任何 ASCII 值,包括 \0。
strrchr

#include <string.h>

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

查找字符串 str 中最后一次出现的字符 c,并返回该字符的指针。如果未找到,则返回 NULL。 c 是一个整数,可以是任何 ASCII 值,包括 \0。
strstr

#include <string.h>

char *strstr(const char *str1, const char *str2);

查找字符串 str2 在字符串 str1 中第一次出现的位置,并返回该位置的指针。如果未找到,则返回 NULL。 str2 不能是空字符串。
strtok

#include <string.h> 
char *strtok(char *str, const char *delim);

将字符串 str 按照分隔符 delim 分割成多个子字符串。每次调用返回下一个子字符串的指针,并在原始字符串中用 \0 替换分隔符

第一次调用时,str 应该是完整的字符串;后续调用时,str 应该传入 NULL。