2016-12-13 6 views
-1

URL(文字列)を読み取り、パターンを検索しています(/の連続した出現)。一致するパターンが見つかった場合は、それを1つの/と置き換えて残りの文字をそのままコピーします。たとえば、入力文字列がhttp://www.yahoo.com/の場合は、http:/www.yahoo.com/の出力を生成する必要があります。これは、その文字が連続して2回発生しているため、余分な文字を取り除いて/です。ここで連続した重複文字を1つの出現文字に置き換えます。

はプログラムです:

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

@tinga文字列リテラルは変更できません。また、すぐに文字列 "//"を見つけるのに役立つ標準関数strstrがあります –

+3

これは奇妙な例です。有効なURIを受け取り、それを無効なものにします。 – paddy

+0

[なぜこの文字列反転Cコードがセグメンテーションフォルトを引き起こすのですか?](http://stackoverflow.com/questions/1614723/why-is-this-string-reversal-c-code-causing-a-segmentation - 障害) – John3136

答えて

1

文字列リテラルは変更できません。それらはCおよびC++で変更不可能です。

要素が適切な値を持つ場合、これらの配列が異なるかどうかは不明です。 プログラムが にそのような配列を変更しようとすると、動作は未定義です。

このタスクは、標準の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); 

のコードスニペットの出力は、離れて、文字列リテラルを変更しようとするから、このループが間違っ

if (found) { 
     for(j = i + 1; j <= (len - i - 2); j++) { 
      str[j] = str[j + 1]; 
     } 
    } 

であるあなたのプログラムについては

http://www.yahoo.com/ 
http:/www.yahoo.com/ 

のようになります。それは少なくとも同じように見えるはずです

if (found) { 
     for(j = i + 1; j < len; j++) { 
      str[j] = str[j + 1]; 
     } 
    } 
0

文字列リテラル(読み取り専用メモリ)で操作しています。文字を変更しようとすると、エラーが発生します。

文字列データを書き込み可能なメモリにコピーしてから変更することができます。

最も簡単な変更は、このラインを作ることです。

char str[] = "http://www.yahoo.com/"; 

しかし、C++のために、あなたの代わりにstd::stringを使用する必要があり、その後、あなたは標準の検索を使用することができます。

unsigned char *str = "http://www.yahoo.com/"; 

ではなく、このうアルゴリズム:

#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; 
} 
関連する問題