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

C语言字符串替换程序调试:str1未正确定义致运行异常

C语言字符串替换程序故障排查与修复

原程序意图是在目标字符串中查找指定子串并替换,但存在多个致命错误导致无法正常运行,核心问题及其他错误的排查与修复如下:

核心错误:字符串未添加终止符

1. str1未正确终止

原程序仅将string的前start个字符复制到str1,但未手动添加字符串终止符'\0',导致str1成为未终止的非法字符串。后续调用strcat、strlen等函数时,会因找不到终止符而读取内存越界,引发乱码或崩溃。

修复:复制完成后立即添加终止符

// 复制string前start个字符到str1
for(int i=0;i<start;i++)
    str1[i]=string[i];
str1[start] = '\0'; // 必须添加,让str1成为合法字符串

2. check数组未正确终止

复制string中start到end的字符到check后,同样未添加'\0',导致strcmp函数读取超出数组范围的内存,匹配结果不可控。

修复:复制完成后添加终止符

// 复制string中start到end的字符到check
for(int i=start;i<end;i++)
    check[i-start]=string[i];
check[end - start] = '\0'; // 等价于check[strlen(s1)] = '\0'

其他致命错误修复

3. start变量未初始化

若输入的s1首字符不在string中,循环不会给start赋值,此时start为随机垃圾值,后续计算end和内存操作会直接崩溃。

修复:初始化start为-1,循环结束后判断是否找到匹配

int start = -1, end, compare;
for(int i=0;string[i]!='\0';i++){
    if(string[i]==s1[0]){
        start=i;
        break;
    }
}
// 未找到匹配直接退出
if(start == -1){
    printf("未找到匹配的字符串\n");
    return 1;
}

4. gets函数存在缓冲区溢出风险

gets不会检查输入长度,若输入超过s1/s2的数组大小(10字节),会直接溢出覆盖内存,引发崩溃或安全问题。

修复:用fgets替代,并手动去除换行符

printf("Enter string 1 ");
fgets(s1, sizeof(s1), stdin);
s1[strcspn(s1, "\n")] = '\0'; // 去掉输入末尾的换行符

printf("Enter string 2 ");
fgets(s2, sizeof(s2), stdin);
s2[strcspn(s2, "\n")] = '\0';

5. if语句逻辑缩进错误

原代码中if(compare==0)仅控制strcat一行,printf会无条件执行,不符合"找到匹配后才输出"的逻辑。

修复:给if块添加大括号,同时修正原程序未使用s2的问题(推测意图是替换为s2)

if(compare==0){
    strcat(str1, s2); // 将匹配的s1替换为s2
    printf("\n替换后的中间字符串:%s", str1);
}

6. 复制剩余字符后未添加终止符

将string中end后的字符复制到str1时,未添加终止符,导致strcpy读取越界。

修复:复制完成后给str1加终止符

int j = strlen(str1);
for(int i=end; string[i]!='\0'; i++){
    str1[j++] = string[i];
}
str1[j] = '\0'; // 添加终止符

7. string数组大小不足

原string是固定大小的数组(仅能容纳原字符串),替换后若长度超过原大小,strcpy会导致缓冲区溢出。

修复:扩大string的数组大小

char string[100] = "We will rock you"; // 预留足够空间

修复后的完整代码

#include<stdio.h>
#include<string.h>
int main()
{
    char string[100] = "We will rock you"; // 扩大数组避免溢出
    char s1[10], s2[10];
    
    printf("Enter string 1 ");
    fgets(s1, sizeof(s1), stdin);
    s1[strcspn(s1, "\n")] = '\0'; // 去除换行符

    printf("Enter string 2 ");
    fgets(s2, sizeof(s2), stdin);
    s2[strcspn(s2, "\n")] = '\0';

    int start = -1, end, compare;
    // 查找s1首字符的位置
    for(int i=0; string[i]!='\0'; i++){
        if(string[i] == s1[0]){
            start = i;
            break;
        }
    }
    if(start == -1){
        printf("未找到匹配的字符串\n");
        return 1;
    }

    end = start + strlen(s1);
    char str1[100], check[10];

    // 复制string前start个字符到str1
    for(int i=0; i<start; i++)
        str1[i] = string[i];
    str1[start] = '\0'; // 添加终止符

    // 复制string中start到end的字符到check
    for(int i=start; i<end; i++)
        check[i-start] = string[i];
    check[end - start] = '\0'; // 添加终止符

    compare = strcmp(check, s1);
    if(compare == 0){
        strcat(str1, s2); // 替换为s2
        printf("\n替换后的中间字符串:%s", str1);
    } else {
        printf("\n未找到完整匹配的字符串\n");
        return 1;
    }

    // 复制string中end之后的剩余字符到str1
    int j = strlen(str1);
    for(int i=end; string[i]!='\0'; i++){
        str1[j++] = string[i];
    }
    str1[j] = '\0'; // 添加终止符

    strcpy(string, str1);
    printf("\n最终结果:%s", string);

    return 0;
}

关于已知漏洞说明

你提到的无法处理重复单词、误匹配包含s1的单词(如s1=ask匹配task)属于逻辑缺陷:

  • 处理重复单词:需要循环查找所有匹配位置,而非找到第一个就停止;
  • 避免部分匹配:匹配s1后需检查前后是否为单词边界(空格、标点或字符串首尾),确保匹配完整单词。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 05:03:21