You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C++代码中strstr指针运算及提取最后子串的疑问

字符串处理代码疑问解析

我无法理解这段代码的工作原理,尤其是i=strstr(s + k, t) - s;这一行。我知道strstr()会返回指针,而这段代码的功能是提取字符串中最后出现的子串,但为何指针减去字符串会得到无符号类型的最后出现位置?我尝试将数据类型改为unsigned或int,调换s的位置(如s - strstr(...)),代码便无法运行。

输入示例:ana si mariana canta la nai和na,输出示例:ana si mariana canta la i

代码如下:

#include <iostream>
#include <cstring>
using namespace std;
char s[256], t[256];
int main()
{
    unsigned i, n, k = 0, x = 0;
    gets(s);
    gets(t);
    n = strlen(t);
    while(k < strlen(s) && x < strlen(s))
    {
        i = strstr(s + k, t) - s;
        k = i + n;
        x = strstr(s + k, t) - s;
    }
    strcpy(s + i, s + i + n);
    cout << s;
    return 0;
}

核心逻辑与疑问拆解

这段代码的实际作用是删除字符串s中最后一次出现的子串t,以下针对你的疑问逐一解释:

1. i = strstr(s + k, t) - s; 的本质

  • strstr(a, b) 会在字符串a中查找子串b,返回第一个匹配位置的指针,找不到则返回NULL。
  • s + k 是指针偏移:数组名s本质是指向字符串首字符的指针,s + k 就是从s的第k个字符开始的子串起始地址。
  • 同类型指针相减的规则:两个指向同一内存块的同类型指针相减,结果是它们之间的元素个数。strstr返回的指针指向s内部的某个字符,减去s(首字符指针),得到的就是该位置距离首字符的偏移量——也就是子串t在s中的起始下标。

2. 为什么调换指针位置会失效?

指针减法有严格要求:只有高地址指针减去低地址指针时,结果才是合法的正下标。如果写成s - strstr(...),相当于用低地址指针减高地址指针,结果会是负数。而i是unsigned类型,负数会被强制转换成超大的无符号数,直接破坏循环逻辑,代码自然无法运行。

3. 关于数据类型的问题

  • 原代码用unsigned存下标是合理的:字符串下标不可能为负,无符号类型能避免负数干扰。但改成int也能正常工作(前提是子串t存在于s中);如果strstr返回NULL(找不到子串),NULL - s会得到负数,赋值给int会保留负数,赋值给unsigned会变成大正数,都会导致后续逻辑崩溃——原代码能运行是因为输入保证了子串存在。
  • 循环的逻辑是不断向后查找下一个子串:每次找到k位置之后的第一个t,记录下标i,然后把k移到i + n(跳过当前找到的t),再查下一个t的位置x。当x超出字符串长度(找不到下一个t),循环停止,此时i就是最后一次出现t的下标,最后用strcpy把i + n开始的内容覆盖到i位置,相当于删除了这个t。

4. 代码的潜在问题

  • gets函数已被C标准废弃,存在缓冲区溢出风险,建议用fgets替代。
  • 未处理strstr返回NULL的情况(比如t不在s中),此时i = NULL - s会生成非法值,直接导致程序崩溃。

内容的提问来源于stack exchange,提问作者nex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 23:25:20