C 字符串截取

在 C 语言中,字符串本质上是以空字符 '\0' 结尾的字符数组。与一些高级语言不同,C 语言的标准库并没有提供一个类似 substring() 这样的函数来直接返回一个新的子字符串。

因此,在 C 语言中实现字符串截取,通常需要我们手动操作内存或者使用一些库函数来间接实现。主要有以下 3 种方式:

  • 使用 strncpy() 函数。
  • 使用指针操作。
  • 复制到新字符串数组。

使用 strncpy() 截取字符串

在 C 语言中,我们可以使用 strncpy() 函数从 “原始字符串” 复制指定数量的字符到 “目标字符串” 。

语法:

strncpy(dest, src, n)

说明:

strncpy() 函数接收以下 3 个参数。

  • dest(char *):指向目标字符串的指针。
  • src(const char *):指向原始字符串的指针。
  • n(size_t):要复制的字符数量。

strncpy(dest, src, n) 表示复制 str 中的前 n 个字符到 dest 中去。

示例 1:

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

int main(void)
{
    char str1[20];
    char str2[] = "JavaScript";

    // 截取字符串
    strncpy(str1, str2, 4);
    // 手动添加空字符
    str1[4] = '\0';

    puts(str1);
    puts(str2);
    
    return 0;
}

运行结果如下。

Java
JavaScript

分析:

strncpy(str1, str2, 4); 表示截取 str2 的前 4 个字符,然后复制到 str1 中去。由于源字符串 "JavaScript" 的长度大于 4,strncpy() 不会自动添加空字符,因此我们需要手动添加 str1[4] = '\0';,以确保 str1 是一个有效的 C 字符串

需要注意的是,如果 str1 本身是有内容的字符串,此时复制过来的内容会直接替换原来的内容,请看下面例子。

示例 2:

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

int main(void)
{
    char str1[] = "Go";
    char str2[] = "Python";

    strncpy(str1, str2, 2);
    str1[2] = '\0';

    puts(str1);
    puts(str2);
    printf("%d\n", strlen(str1));
    printf("%d", strlen(str2));
    
    return 0;
}

运行结果如下。

Py
Python
2
6

分析:

strncpy(str1, str2, 2); 表示截取 str2 的前 2 个字符("Py"),然后复制到 str1 中去。由于源字符串 "JavaScript" 的长度大于 4,strncpy() 不会自动添加空字符,因此我们需要手动添加 str1[4] = '\0';,以确保 str1 是一个有效的 C 字符串。

使用指针截取字符串

使用指针来截取字符串,这种方法最为简单,但需要注意它并没有创建新的字符串,而是让一个新的指针指向原始字符串的某个位置。

提示: 对于指针,我们在后续的 “C 指针” 这一节会详细介绍。

示例 3:

#include <stdio.h>

int main(void) 
{
    char str[] = "lvyenet";
    char *subStr = &str[4];    // 从索引 4 开始截取

    printf("原始字符串: %s\n", str);
    printf("截取的子串: %s\n", subStr);

    return 0;
}

运行结果如下。

原始字符串: lvyenet
截取的子串: net

分析:

在上面例子中,我们创建了一个指向 str 数组中索引为 4 的元素的指针 subStr。由于 C 语言中字符串是以空字符 '\0' 结尾的,当我们使用 “%s” 格式符打印 subStr 时,会从 subStr 指向的位置开始打印,直到遇到空字符为止。需要注意的是,这种方法并没有创建新的字符串,subStr 仍然指向原始字符串 str 的一部分。

复制到新的字符数组

这种方法会创建一个新的字符数组,并将原始字符串中需要截取的部分复制到这个新的数组中。

示例 4:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义函数
char *substring(const char *str, int start, int length) 
{
    // 错误处理
    if (str == NULL || start < 0 || length <= 0) 
    {
        return NULL; 
    }

    int str_len = strlen(str);

    // 如果起始索引超出范围
    if (start >= str_len) 
    {
        return NULL; 
    }

    // 如果截取长度不能超过剩余长度
    if (start + length > str_len) 
    {
        length = str_len - start; 
    }

    // 分配内存
    char *sub = malloc(sizeof(char) * (length + 1)); 

    // 如果内存分配失败
    if (sub == NULL) 
    {
        return NULL; 
    }

    strncpy(sub, str + start, length);

    // 添加空字符结尾
    sub[length] = '\0'; 

    return sub;
}

int main(void) 
{
    char str[] = "www.lvyenet.com";

    // 从索引 4 开始截取长度为 7 的子字符串
    char *sub_str = substring(str, 4, 7); 

    if (sub_str != NULL) 
    {
        printf("原始字符串: %s\n", str);
        printf("截取的子串: %s\n", sub_str);
        // 释放动态分配的内存
        free(sub_str);
    } 
    else 
    {
        printf("截取失败\n");
    }
    return 0;
}

运行结果如下。

原始字符串: www.lvyenet.com
截取的子串: lvyenet

分析:

在这个例子中,我们自定义实现了一个名为 “substring” 的函数,该函数用于实现字符串的截取。substring() 函数会返回一个指向新分配内存的指针,该内存存储着截取的子字符串。

substring(str, 4, 7) 表示从 str 中截取了从索引 4 开始,长度为 7 的子字符串。在 main 函数中,我们打印了这个子字符串,并在使用完之后使用 free() 函数释放了分配的内存,以避免内存泄漏。

上一篇: C 字符串比较

下一篇: C 字符串分割

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号