C语言如何实现instr字符串查找功能?

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

Instr 函数的核心功能是:在一个字符串(源字符串)中查找另一个字符串(子字符串)第一次出现的位置

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

在 C 语言标准库中,并没有一个直接叫 instr 的函数,我们可以使用标准库中强大的字符串处理函数来轻松实现它,最常用的就是 strstr

使用标准库函数 strstr (最推荐)

strstr 是 C 标准库 <string.h> 中的一个函数,它的原型是:

char *strstr(const char *haystack, const char *needle);
  • haystack: 源字符串,即被搜索的字符串。
  • needle: 子字符串,即要查找的字符串。

返回值:

  • 如果找到 needlestrstr 返回一个指向 haystackneedle 首次出现位置的指针。
  • 如果没有找到,strstr 返回 NULL

如何将指针转换为“位置” (索引)Instr 通常返回一个从 1 开始的整数索引,而 strstr 返回的是指针,我们可以通过计算指针与源字符串首地址的差值来得到从 0 开始的索引,+1 即可得到从 1 开始的索引。

示例代码:实现 my_instr 函数

下面我们封装一个自己的 my_instr 函数,使其行为与 VB 的 Instr 函数一致。

#include <stdio.h>
#include <string.h> // 必须包含这个头文件
/**
 * @brief 模拟 VB 的 Instr 函数
 * @param src_str 源字符串
 * @param sub_str 要查找的子字符串
 * @return 如果找到,返回子字符串在源字符串中首次出现的起始位置 (从1开始);
 *         如果未找到或源字符串为空,返回 0。
 */
int my_instr(const char *src_str, const char *sub_str) {
    // 1. 检查源字符串或子字符串是否为空指针
    if (src_str == NULL || sub_str == NULL) {
        return 0;
    }
    // 2. 使用 strstr 查找子字符串
    const char *pos = strstr(src_str, sub_str);
    // 3. 判断是否找到
    if (pos != NULL) {
        // 找到了,计算位置
        // pos - src_str 得到从 0 开始的偏移量
        // +1 使其从 1 开始,符合 Instr 的习惯
        return (int)(pos - src_str) + 1;
    } else {
        // 没找到,返回 0
        return 0;
    }
}
int main() {
    const char *text = "Hello, welcome to the world of C programming!";
    const char *word1 = "world";
    const char *word2 = "C";
    const char *word3 = "Python"; // 不存在的单词
    // 查找 "world"
    int pos1 = my_instr(text, word1);
    printf("'%s' found at position: %d\n", word1, pos1); // 应该输出 21
    // 查找 "C"
    int pos2 = my_instr(text, word2);
    printf("'%s' found at position: %d\n", word2, pos2); // 应该输出 31
    // 查找不存在的 "Python"
    int pos3 = my_instr(text, word3);
    printf("'%s' found at position: %d\n", word3, pos3); // 应该输出 0
    // 测试子字符串在开头的情况
    const char *text2 = "apple banana";
    int pos4 = my_instr(text2, "apple");
    printf("'%s' found at position: %d\n", "apple", pos4); // 应该输出 1
    // 测试子字符串就是源字符串本身的情况
    int pos5 = my_instr(text2, text2);
    printf("'%s' found at position: %d\n", text2, pos5); // 应该输出 1
    return 0;
}

代码解释:

  1. #include <string.h>: 引入 strstr 函数所在的头文件。
  2. my_instr 函数:
    • 参数是 const char*,表示我们不打算修改这些字符串,符合 strstr 的用法。
    • 首先进行空指针检查,这是一个好习惯。
    • 调用 strstr 进行查找。
    • 根据 strstr 的返回值进行判断。
    • (pos - src_str) 是指针算术,它计算了两个地址之间的差值,这个差值正好是子字符串在源字符串中的起始索引(从 0 开始)。
    • + 1 将其转换为从 1 开始的索引。
    • 如果没找到,返回 0。

手动实现字符串查找 (不使用 strstr)

为了更深入地理解字符串查找的原理,我们可以不使用 strstr,而是自己用循环来实现这个逻辑,这有助于理解底层算法。

基本思路:

  1. 遍历源字符串的每一个字符,作为可能的匹配起点。
  2. 对于每一个起点,检查从这个位置开始的后续字符是否与子字符串完全匹配。
  3. 如果完全匹配,就返回当前起点的位置。
  4. 如果遍历完整个源字符串都没有找到,则返回 0。

示例代码:手动实现 my_instr_manual

#include <stdio.h>
/**
 * @brief 手动模拟 Instr 函数,不使用 strstr
 * @param src_str 源字符串
 * @param sub_str 要查找的子字符串
 * @return 如果找到,返回子字符串在源字符串中首次出现的起始位置 (从1开始);
 *         如果未找到或源字符串/子字符串为空,返回 0。
 */
int my_instr_manual(const char *src_str, const char *sub_str) {
    if (src_str == NULL || sub_str == NULL || *sub_str == '\0') {
        // 如果任一字符串为空指针,或者子字符串为空字符串,返回 0
        return 0;
    }
    int i = 0; // 遍历源字符串的索引
    while (src_str[i] != '\0') {
        int j = 0;
        // 检查从 src_str[i] 开始是否匹配 sub_str
        while (src_str[i + j] == sub_str[j] && sub_str[j] != '\0') {
            j++;
        }
        // j 移动到了 sub_str 的末尾,说明完全匹配
        if (sub_str[j] == '\0') {
            return i + 1; // 返回从 1 开始的位置
        }
        i++; // 继续检查源字符串的下一个字符作为起点
    }
    // 遍历完源字符串都没找到
    return 0;
}
int main() {
    const char *text = "Hello, welcome to the world of C programming!";
    const char *word1 = "world";
    const char *word2 = "C";
    int pos1 = my_instr_manual(text, word1);
    printf("Manual search: '%s' found at position: %d\n", word1, pos1);
    int pos2 = my_instr_manual(text, word2);
    printf("Manual search: '%s' found at position: %d\n", word2, pos2);
    return 0;
}

代码解释:

  • 外层 while 循环遍历源字符串 src_str
  • 内层 while 循环尝试匹配子字符串 sub_str
  • src_str[i + j] == sub_str[j] 比较当前字符是否相等。
  • sub_str[j] != '\0' 确保我们不会越界读取 sub_str
  • 如果内层循环因为 sub_str[j] 到达末尾 ('\0') 而退出,说明匹配成功,返回 i + 1
  • 如果内层循环因为字符不匹配而退出,外层循环的 i 会增加,继续下一次尝试。

总结与对比

特性 strstr (方法一) 手动实现 (方法二)
优点 简洁、高效、标准,由 C 标准库提供,通常经过高度优化。 有助于理解算法,不依赖特定库,适合学习。
缺点 返回的是指针,需要额外计算才能得到索引。 代码复杂,容易出错,性能可能不如标准库实现。
适用场景 实际开发中首选,代码清晰,可读性高。 学术练习、面试、或者在不允许使用 string.h 的极端环境中。

在日常的 C 语言编程中,你应该优先使用 strstr 来实现 Instr 的功能,它更简洁、更安全,并且性能更有保障,手动实现的方法则更多地用于学习和理解字符串匹配的基本原理。

-- 展开阅读全文 --
头像
C语言estimate
« 上一篇 04-17
织梦手机端如何添加与适配?
下一篇 » 04-17

相关文章

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

目录[+]