C语言实现字符串替换函数:面试避坑与代码解析
在C/C++面试中,字符串替换(如将空格转为%20)是考察基础功底与边界意识的高频题目。正确实现需兼顾时间效率与内存安全,避免栈溢出与野指针访问。
原题分析与核心考点
面试题通常要求将一个字符串中的指定子串替换为另一子串。例如,将空格替换为 %20。此类题目主要考察以下能力:
- 算法规范:不能硬编码特定字符,需设计通用函数接口。
- 代码鲁棒性:参数校验、空指针检测、内存边界检查。
- 可移植性:不依赖非标准库(如C98标准的
gets存在安全隐患)。
第1步:理解原始代码的逻辑
原题提供的代码采用了一次遍历方式,逻辑如下:
- 遍历源字符串
parr。 - 若当前字符不等于目标字符
e1,直接复制到结果缓冲区arr2。 - 若等于
e1,则将替换串e2逐字符写入arr2。
原题意图解与输入输出示意
第2步:识别代码中的致命缺陷
尽管上述思路时间复杂度为 O(n),但原版实现存在严重错误,直接运行会导致程序崩溃或未定义行为:
- 栈溢出风险:
char arr2[100]固定在栈上。若源字符串长度超过限制,或替换后总长度超过100字节,将导致栈溢出。 - 未初始化/内存越界:代码假设替换后的长度不超过100,但未动态检查
len + (count * (len2 - len1))是否溢出。 - 返回局部变量地址:
return arr2;返回了栈上临时数组的指针,函数结束后该内存可能被覆盖,导致调用者获取垃圾数据。 - 使用不安全函数:主函数中使用
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++底层编程与面试技巧的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









