我正在读取 URL(字符串)并搜索模式(连续出现
/
字符)。如果我找到匹配的模式,我想将其替换为单个 /
并按原样复制其余字符。例如:如果输入字符串是 http://www.yahoo.com/
,我需要通过删除额外的 http:/www.yahoo.com/
来生成输出 /
,因为该字符连续出现两次。
这是程序:
int main() {
int i, j;
bool found = false;
unsigned char *str = "http://www.yahoo.com/";
int len = strlen(str);
for (i = 0; i < len - 1; i++) {
if ((str[i] == '/') && (str[i + 1] == '/')) {
found = true;
break;
}
}
if (found) {
for (j = i + 1; j <= (len - i - 2); j++) {
str[j] = str[j + 1];
}
}
return 0;
}
但是这个程序正在生成分段错误。这段代码的问题出在哪里?知道如何修复它吗?有替代的简单实现吗?
您不得更改字符串文字。它们在 C 和 C++ 中是不可修改的。根据 C 标准(6.4.5 字符串文字)
7 未指定这些数组是否不同,只要它们的 元素具有适当的值。 如果程序尝试 修改这样的数组,行为是未定义的。
strstr()
和 memmove()
可以轻松完成该任务。例如
char s[] = "http://www.yahoo.com/";
puts(s);
char *p = strstr(s, "//");
if (p) memmove(p, p + 1, strlen(s) - (p - s));
puts(s);
代码片段的输出将如下所示
http://www.yahoo.com/
http:/www.yahoo.com/
对于你的程序来说,除了尝试更改字符串文字之外,这个循环是错误的
if (found) {
for(j = i + 1; j <= (len - i - 2); j++) {
str[j] = str[j + 1];
}
}
它至少应该看起来像
if (found) {
for(j = i + 1; j < len; j++) {
str[j] = str[j + 1];
}
}
您正在操作字符串文字,它是只读存储器。当您尝试修改字符时,会出现错误。
将字符串数据复制到可写内存中,然后就可以修改它了。
最简单的改变就是做这行:
unsigned char *str = "http://www.yahoo.com/";
改为这样:
char str[] = "http://www.yahoo.com/";
但是,对于 C++,您应该使用
std::string
来代替,然后您可以使用标准搜索算法,如下所示:
#include <string>
int main() {
std::string str = "http://www.yahoo.com/";
std::string::size_type i = 0;
do {
i = str.find("//", i);
if (i == std::string::npos) break;
str.erase(i, 1);
}
while (!str.empty());
return 0;
}
或者:
#include <string>
#include <algorithm>
bool isBackslashPair(const char c1, const char c2) {
return ((c1 == '/') && (c2 == '/'));
}
int main() {
std::string str = "http://www.yahoo.com/";
std::string::iterator iter = str.begin();
do {
iter = std::adjacent_find(iter, str.end(), isBackslashPair);
if (iter == std::string::end()) break;
iter = str.erase(iter);
}
while (!str.empty());
return 0;
}