C语言实现字符串替换函数:面试避坑与代码解析

Chloe
Chloe
发布时间:2026-10-13| 8人浏览过
原创

在C/C++面试中,字符串替换(如将空格转为%20)是考察基础功底与边界意识的高频题目。正确实现需兼顾时间效率与内存安全,避免栈溢出与野指针访问。

原题分析与核心考点

面试题通常要求将一个字符串中的指定子串替换为另一子串。例如,将空格替换为 %20。此类题目主要考察以下能力:

  • 算法规范:不能硬编码特定字符,需设计通用函数接口。
  • 代码鲁棒性:参数校验、空指针检测、内存边界检查。
  • 可移植性:不依赖非标准库(如C98标准的gets存在安全隐患)。

第1步:理解原始代码的逻辑

原题提供的代码采用了一次遍历方式,逻辑如下:

  1. 遍历源字符串 parr。
  2. 若当前字符不等于目标字符 e1,直接复制到结果缓冲区 arr2。
  3. 若等于 e1,则将替换串 e2 逐字符写入 arr2。

原题意图解与输入输出示意

第2步:识别代码中的致命缺陷

尽管上述思路时间复杂度为 O(n),但原版实现存在严重错误,直接运行会导致程序崩溃或未定义行为:

  1. 栈溢出风险:char arr2[100] 固定在栈上。若源字符串长度超过限制,或替换后总长度超过100字节,将导致栈溢出。
  2. 未初始化/内存越界:代码假设替换后的长度不超过100,但未动态检查 len + (count * (len2 - len1)) 是否溢出。
  3. 返回局部变量地址:return arr2; 返回了栈上临时数组的指针,函数结束后该内存可能被覆盖,导致调用者获取垃圾数据。
  4. 使用不安全函数:主函数中使用 gets() 读取输入,该函数已废弃且极易引发缓冲区攻击。

第3步:构建安全的替换函数

为确保代码可用,建议采用“双指针”法(原地修改,仅适用于替换后长度<=原长度)或“辅助缓冲区”法(适用于任意长度)。鉴于原题场景涉及多换一(如一个空格变三个字符),必须使用足够大的缓冲区或动态分配内存。

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

/**
 * 安全版字符串替换函数
 * @param input   输入字符串
 * @param e1      要查找的子串
 * @param e2      替换成的子串
 * @param output  输出缓冲区(需确保容量充足)
 * @param buf_size 输出缓冲区大小
 * @return        成功返回0,失败返回-1
 */
int replace_str(const char* input, const char* e1, const char* e2, char* output, size_t buf_size)
{
    // 1. 参数校验:鲁棒性第一步
    assert(input != NULL);
    assert(e1 != NULL);
    assert(e2 != NULL);
    assert(output != NULL);

    if (*e1 == '\0') {
        strncpy(output, input, buf_size - 1);
        output[buf_size - 1] = '\0';
        return 0;
    }

    size_t input_len = strlen(input);
    size_t e1_len = strlen(e1);
    size_t e2_len = strlen(e2);
    
    // 2. 计算替换后的大致长度,预检溢出
    // 简单估算:最坏情况全替换
    size_t estimated_len = input_len / e1_len * e2_len + (input_len % e1_len) + 1;
    // 注意:精确计算需要遍历统计,此处简化处理,实际应严格计算
    // 为演示严谨性,这里使用更保守的复制策略

    size_t i = 0; // 读指针
    size_t j = 0; // 写指针

    while (input[i] != '\0' && j < buf_size - 1) {
        // 检查是否匹配 e1
        int match = 1;
        for (size_t k = 0; k < e1_len; ++k) {
            if (input[i + k] != e1[k]) {
                match = 0;
                break;
            }
        }

        if (match) {
            // 写入替换串 e2
            for (size_t k = 0; k < e2_len; ++k) {
                output[j++] = e2[k];
                if (j >= buf_size) goto cleanup_error; // 检查缓冲区剩余空间
            }
            i += e1_len; // 跳过已匹配的 e1
        } else {
            // 未匹配,直接复制当前字符
            output[j++] = input[i++];
        }
    }

    output[j] = '\0';
    return 0;

cleanup_error:
    return -1;
}

void test_replacement() {
    char input[] = "Hello World";
    char output[200];
    
    if (replace_str(input, " ", "%20", output, sizeof(output)) == 0) {
        printf("Result: %s\n", output);
    } else {
        printf("Buffer overflow or error!\n");
    }
}

第4步:验证与测试

使用修正后的代码进行测试,观察输出是否符合预期:

修正后代码的运行结果示意

通过引入明确的缓冲区大小检查和参数断言,可有效防止内存越界和段错误。面试官通常更看重对 NULL 检查、边界条件以及内存管理的思考过程。

总结

C语言字符串操作的核心在于“边界”。简单的替换逻辑虽短,但在工程中必须考虑内存分配、长度计算和安全API的使用。以上就是关于C语言实现字符串替换函数的详细内容,更多关于C/C++底层编程与面试技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。