C语言多子串替换问题求助:将指定子串替换为星号
解决多子串替换为星号的C程序问题
你好!我看了你的代码,确实在多子串替换的实现上有几个需要调整的地方,我先梳理问题点,再给你修正后的完整实现:
现有代码的核心问题
- 不安全的
gets()函数:gets()完全不检查输入长度,很容易造成缓冲区溢出,强烈建议用fgets()替代,同时要处理输入末尾的换行符。 - 变长数组顺序错误:第二个版本里你先定义了
char substr[n][100];,但此时n还没赋值,这不符合C标准(变长数组的大小必须是已经确定的变量),得先读n再定义数组。 - 变量名笔误:代码里的
cuv[i]是拼写错误,应该是substr[i]。 - 仅替换第一个匹配项:现有代码用
strstr()只找得到第一个匹配的子串,不会处理字符串中重复出现的同一子串。 - 输入缓冲区残留问题:
scanf("%d", &n)执行后,输入缓冲区会留下换行符,导致后续读取子串时可能直接读到空内容。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char str[5120]; int n; // 读取初始字符串,替换不安全的gets() printf("Type the string:\n"); if (fgets(str, sizeof(str), stdin) == NULL) { fprintf(stderr, "Failed to read string\n"); return 1; } // 去掉fgets读取的换行符(如果存在) str[strcspn(str, "\n")] = '\0'; // 读取待修改子串的数量 printf("How many substrings to modify? "); if (scanf("%d", &n) != 1 || n <= 0) { fprintf(stderr, "Invalid number of substrings\n"); return 1; } // 清除scanf后残留的换行符,避免影响后续输入 while (getchar() != '\n'); // 定义子串数组(现在n已经赋值,变长数组合法) char substr[n][100]; // 读取所有待修改子串 printf("\nType the substrings (each up to 99 characters):\n"); for (int i = 0; i < n; i++) { printf("Substring %d: ", i + 1); if (fgets(substr[i], sizeof(substr[i]), stdin) == NULL) { fprintf(stderr, "Failed to read substring %d\n", i + 1); return 1; } // 去掉子串的换行符 substr[i][strcspn(substr[i], "\n")] = '\0'; // 检查子串是否为空 if (strlen(substr[i]) == 0) { fprintf(stderr, "Substring %d cannot be empty\n", i + 1); return 1; } } // 处理每个子串的替换(替换所有出现的匹配项) for (int i = 0; i < n; i++) { const char *sub = substr[i]; size_t sub_len = strlen(sub); char *pos = str; // 循环查找所有匹配的子串,直到找不到为止 while ((pos = strstr(pos, sub)) != NULL) { // 将匹配到的子串替换为* memset(pos, '*', sub_len); // 移动指针,避免重复替换同一位置(比如子串是"aa",替换后变成"**",不会再匹配) pos += sub_len; } } // 输出修改后的字符串 printf("\nThe modified string is:\n%s\n", str); return 0; }
关键改进说明
- 安全输入处理:用
fgets()替代gets(),并通过strcspn()自动去掉输入末尾的换行符,避免字符串里带多余的换行。 - 正确的变长数组使用:先读取
n的值,再定义substr[n][100],符合C标准对变长数组的要求。 - 替换所有匹配项:通过
while循环反复调用strstr(),直到找不到子串为止,确保所有出现的目标子串都被替换成*。 - 输入缓冲区清理:在
scanf("%d", &n)后,用while (getchar() != '\n')清空残留的换行符,避免后续fgets()读到空内容。 - 基础错误处理:增加了输入失败的判断,比如读取字符串或子串失败时给出错误提示,让程序更健壮。
额外小提示
如果你需要支持更复杂的场景(比如大小写不敏感匹配、重叠子串处理),可以自己实现自定义的匹配函数替代strstr()。另外,如果初始字符串可能超过5120字节,可以考虑用malloc()动态分配内存,避免栈溢出。
内容的提问来源于stack exchange,提问作者Saledin Mert Aykut
相关产品推荐
相关产品推荐

