用单次出现替换连续的重复字符

时间:2016-12-13 01:05:40

标签: c++ c

我正在读取一个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;
}

但是这个程序正在产生分段错误。这段代码中的问题在哪里?知道怎么解决吗?对此有任何替代的简单实现吗?

2 个答案:

答案 0 :(得分:1)

您可能无法更改字符串文字。它们在C和C ++中是不可修改的。根据C标准(6.4.5字符串文字)

  

7未指明这些阵列是否与它们不同   元素具有适当的值。 如果程序尝试   修改这样的数组,行为是未定义的。

使用标准C函数strstr可以轻松完成任务。例如

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];
        }
    }

答案 1 :(得分:0)

您正在使用字符串文字,这是只读内存。当您尝试修改字符时,会出现错误。

将您的字符串数据复制到可写内存中,然后您可以修改它。

最简单的改变就是建立这一行:

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;
}