2012-01-09 24 views
2

私はこれを行うことができることを知っていますstr.c_str()、 しかし、私は文字を定数にしたくありません。私はいくつかの変更を加えることができるようにチャーが欲しいです。文字列を文字列に変換する

char* removeDup(char *s) 
{ 


     int len = strlen(s); 
     int p,q, idx = -1; 
    for(p = 0; p< len; p++) 
    { 
    char temp = s[p]; 
    bool flag = true; 
    for(q=0;q<p;q++) 
    { 
     if(s[q] == temp) 
     { 
      flag = false; 
      break; 
     } 
    } 
    if(flag == true) 
    { 
     s[++idx] = temp; 
    } 
} 
    s[++idx] = '\0'; 
    return s; 
} 

この関数を以下のように呼び出すと、エラーが発生します。

string s = "abcde"; 
removeDuplicate(s.c_str()); 

私はこのscharなくconst charに変換する必要があります。両方とも、

string::data()またはstring::c_str()const char *を返す:あなたが使用することができますstd::stringから基礎データを取得するために

+10

私の提案は、 '代わりにSTRING'と'文字をスキップ* '完全 – Default

答えて

5

どちらの場合でも、返されるデータは、ユーザープログラムが変更できない一部の読み取り専用実装定義領域に割り当てられているため、const char *です。返されたconst char *を変更しようとすると、未定義の動作になります。

返された文字列を(const_castで)変更することはできません。

、新しいchar*を作成することでこれを実現して割り当て、const char*から内容にコピーするための唯一の正しい方法:

std::string myString = "blabla"; 
char* myPtr = new char[myString.size() + 1]; 
myString.copy(myPtr, myString.size()); 
myPtr[myString.size()] = '\0'; 
+0

おかげで合格するだろうが、私はその後、' const_castをを '使用しますが、それは悪いアイデアだ余分なバッファ – Roger

+0

@Rogerを使用したくありません。適切な解決策は、@ Luchian Grigoreが示唆するようにデータをコピーすることです。 –

+1

@Rogerまあ、それは不可能です。 'char *'へのCスタイルのキャストは、未定義の動作を引き起こすので、プログラムを中断させます。あなたが望むものを得るためにstd:stringの関数を使わないのはなぜですか? –

2

私はあなたの関数を呼び出して、バッファのコピーを作成することを示唆しています、元の文字列を新しいcharバッファに設定します。ような何か:

std::string str("some string"); 
char tmp[str.length() + 1]; 
memset(tmp, 0, sizeof(tmp)); 
copy(str.begin(), str.end(), tmp); 
str = removeDup(tmp); 

直接)c_str(によって返さconstのバッファを使用し、それがトラブルを求めている修正します。バッファは文字列オブジェクトによって所有されているため、カプセル化を破るように、少なくとも実装に依存して変更することを考えなければなりません。文字列から文字の

コピーシーケンス: http://www.cplusplus.com/reference/string/string/copy/

例えば

+0

constをキャストしてカプセル化を破ること(おそらく誰かが逃げることができる)を破ること以上に、保証されている未定義の動作です。 –

+0

可変長配列はC++の非標準拡張です。移植性を望むなら 'std :: vector 'を使ってください。 –

0

は、私はあなたが文字列から、このメソッドをしたいと思います。文字列 'str'がある場合は、これを行うことができます:

char buf[str.len()+1] 
str.copy(buf, str.len()) 

//terminate with newline 
buf[str.len() = '\n'] 

希望することができます。

1

そのままコピーしてください。

string str = "Hello"; 
char * cStr = new char[str.size()]; 
memcpy(cStr, str.c_str(), str.size()); 
+0

そして、あなたが終わったらダイナミック配列を削除することを忘れないでください(または 'std :: vector 'を使うことをお勧めします)。また、問題のevil関数はゼロ終端文字列を必要とするように見えるので、 'str.size()+ 1'を使用して終端文字を含めるようにしてください。 –

1

合法std::stringに変更を加えるための唯一の方法は、 介して、それが(それらが間接的 が提供するアクセスパスを含む)メンバ関数ですあります。したがって、あなたは、引数として std::string::iteratorを取るために、あなたのremoveDupを書き換える必要があり、何かのように:。

std::string 
removeDup(std::string& original) 
{ 
    std::string::iterator current = original.begin(); 
    std::string::iterator end = original.end(); 
    while (current != end) { 
     end = std::remove(current + 1, end, *current); 
     ++ current; 
    } 
    original.erase(end, original.end()); 
    return original; 
} 

(私はこれがあなたの元のコードは、私が 、確認することはできません何んだと思う私は本当に分からなかったので、

デザインの観点から見ると、これは醜いです。おそらく std::string const&を渡し、新しいstd::stringを返す必要があります:

std::string 
removeDup(std::string const& original) 
{ 
    std::string results; 
    std::bitset<UCHAR_MAX + 1> alreadySeen; 
    for (std::string::const_iterator current = original.begin(); 
      current != original.end(); 
      ++ current) { 
     if (! alreadySeen.test(static_cast<unsigned char>(*current))) { 
      results += *current; 
      alreadySeen.set(static_cast<unsigned char>(*current)); 
     } 
    } 
    return results; 
} 

あなたはstd::stringからchar*を取得したいだけの時間がレガシーコード(またはC)に それを渡すことです。このような場合、std::string::c_str()は 承認済みメソッドです。あなたが呼び出している関数はchar*、 を必要とする場合:

  • 関数は実際に(それが正しい をCONSTていないが、これは多くのC関数の場合の)文字列を変更しない場合、使用しますstd::string::c_str()の戻り値の const_cast、そうでない場合は

  • ローカルバッファを割り当てて、それを渡す必要があります。

    のstd ::ベクトルlocalBuffer(s.begin()、s.end()); localBuffer.push_back( '\ 0'); legacyFunction(& localBuffer [0]、localBuffer.size());あなたができる「賢明な」とは対照的に、「可能性」の分野で

0

std::string str("foo"); 
str = removeDup(std::auto_ptr<char>(strdup(str.c_str()).get()); 

しかし、STDの面で書き換え:: stringが良いだろう。

+1

これは、mallocとnewがcharに対して同義であると仮定しています。 –

関連する問題