C语言strrstr函数如何实现?

99ANYc3cd6
预计阅读时长 18 分钟
位置: 首页 C语言 正文

在C语言中,并没有一个名为 strrstr 的标准库函数,我们可以根据它的命名和常见用法来推断它的功能。

c语言 strrstr
(图片来源网络,侵删)

strrstr 这个名字可以理解为 "string reverse string" 或 "string right string",它的功能通常是:在一个字符串(haystack)中,从后向前查找,最后一次出现另一个字符串(needle)的位置

这与标准库中的 strstr 函数形成对比:

  • strstr(haystack, needle): 从 haystack 的开头开始,查找 needle 第一次出现的位置。
  • strrstr(haystack, needle): 从 haystack 的末尾开始,查找 needle 最后一次出现的位置。

如何实现 strrstr 函数?

由于C标准库中没有这个函数,我们需要自己实现,实现 strrstr 最直接的方法是:

  1. 使用 strstr 在一个循环中不断查找子字符串。
  2. 每次找到子字符串后,记录下它的起始位置。
  3. 然后从该位置的下一个字符继续查找,直到 strstr 返回 NULL(表示再也找不到子字符串了)。
  4. 最后返回记录下的最后一个位置。

下面是一个完整的实现示例:

c语言 strrstr
(图片来源网络,侵删)

循环调用 strstr

这种方法最直观,易于理解。

#include <stdio.h>
#include <string.h>
/**
 * @brief 在字符串中查找子字符串最后一次出现的位置
 * 
 * @param haystack 被搜索的字符串
 * @param needle 要查找的子字符串
 * @return char* 返回一个指向 haystack 中 needle 最后一次出现的起始位置的指针。
 *               如果未找到 needle,则返回 NULL。
 */
char* my_strrstr(const char* haystack, const char* needle) {
    // 1. 处理边界情况:needle 是空字符串
    // 根据标准 strstr 的行为,needle 是空字符串,返回 haystack
    if (*needle == '\0') {
        return (char*)haystack;
    }
    char* last_found = NULL;
    char* current_pos = (char*)haystack;
    // 2. 循环查找,直到再也找不到 needle
    while ((current_pos = strstr(current_pos, needle)) != NULL) {
        // 3. 记录本次找到的位置
        last_found = current_pos;
        // 4. 从找到位置的下一个字符继续查找
        current_pos++;
    }
    // 5. 返回最后一次找到的位置,如果从未找到则为 NULL
    return last_found;
}
int main() {
    const char* text = "this is a test string, this is only a test.";
    const char* word1 = "test";
    const char* word2 = "is";
    const char* word3 = "nonexistent";
    const char* empty_str = "";
    // 测试1: 查找 "test"
    char* result1 = my_strrstr(text, word1);
    if (result1) {
        printf("'%s' 的最后一次出现位置: %ld\n", word1, result1 - text);
        // 输出: "test" 的最后一次出现位置: 31
    } else {
        printf("未找到 '%s'\n", word1);
    }
    // 测试2: 查找 "is"
    char* result2 = my_strrstr(text, word2);
    if (result2) {
        printf("'%s' 的最后一次出现位置: %ld\n", word2, result2 - text);
        // 输出: "is" 的最后一次出现位置: 23
    } else {
        printf("未找到 '%s'\n", word2);
    }
    // 测试3: 查找不存在的字符串
    char* result3 = my_strrstr(text, word3);
    if (result3) {
        printf("'%s' 的最后一次出现位置: %ld\n", word3, result3 - text);
    } else {
        printf("未找到 '%s'\n", word3); // 输出: 未找到 'nonexistent'
    }
    // 测试4: 查找空字符串
    char* result4 = my_strrstr(text, empty_str);
    if (result4) {
        printf("空字符串的查找结果: %ld\n", result4 - text); // 应该是 0
    } else {
        printf("未找到空字符串\n");
    }
    return 0;
}

手动实现(不依赖 strstr

如果你想在不使用 strstr 的情况下实现 strrstr,可以手动遍历字符串进行比较。

#include <stdio.h>
/**
 * @brief 手动实现 strrstr
 * 
 * @param haystack 被搜索的字符串
 * @param needle 要查找的子字符串
 * @return char* 返回一个指向 haystack 中 needle 最后一次出现的起始位置的指针,否则返回 NULL。
 */
char* my_strrstr_manual(const char* haystack, const char* needle) {
    if (*needle == '\0') {
        return (char*)haystack;
    }
    const char* h_ptr = haystack;
    const char* last_found = NULL;
    int needle_len = 0;
    // 计算 needle 的长度
    while (needle[needle_len] != '\0') {
        needle_len++;
    }
    // 外层循环遍历 haystack
    while (*h_ptr != '\0') {
        const char* h_temp = h_ptr;
        const char* n_temp = needle;
        int match = 1;
        // 内层循环比较字符
        while (*n_temp != '\0') {
            if (*h_temp != *n_temp) {
                match = 0;
                break;
            }
            h_temp++;
            n_temp++;
        }
        // 如果匹配成功
        if (match) {
            last_found = h_ptr;
            // 跳过已匹配的部分,继续向后查找
            h_ptr += needle_len;
        } else {
            // 如果不匹配,只前进一个字符
            h_ptr++;
        }
    }
    return (char*)last_found;
}
int main() {
    const char* text = "this is a test string, this is only a test.";
    const char* word = "test";
    char* result = my_strrstr_manual(text, word);
    if (result) {
        printf("手动实现的 '%s' 最后一次出现位置: %ld\n", word, result - text);
    } else {
        printf("未找到 '%s'\n", word);
    }
    return 0;
}

特性 strstr strrstr (自定义)
功能 查找子字符串第一次出现的位置 查找子字符串最后一次出现的位置
标准库 (<string.h>) ,需要自己实现
实现思路 从头开始线性查找 循环调用 strstr 或手动从后向前/从前向后查找
常见用途 解析配置文件、URL、日志等,查找特定标记 获取文件扩展名(查找最后一个 )、从路径中提取文件名等

对于大多数情况,方法一(循环调用 strstr 是最佳选择,因为它代码简洁、可读性高,并且复用了标准库已经高度优化的代码。

-- 展开阅读全文 --
头像
dede图集采集规则如何设置?
« 上一篇 04-15
LinkNote是什么?C语言如何实现?
下一篇 » 04-15

相关文章

取消
微信二维码
支付宝二维码

目录[+]