2011-08-24 16 views
1

C++でカスタムCタイプの文字列クラスを作成する必要があります。私はこれを動作させるのに問題があります。現時点では、私のコードは実行時エラーで起動時にクラッシュします。関数の多くが間違っていることも知っていますが、他の関数を修正する前にメンバ関数をソートする必要があります。関数プロトタイプはすべて私たちに与えられたものであり、私はそれらを変更できないことを覚えておいてください。私は話すために '勇気'を書く必要があります。C++でカスタムCタイプの文字列クラスを作成する

私のコンストラクタが最初に間違っていますか?

#include <iostream> 
#include "tstr.h" 
using namespace std; 

//Default constructor to initialize the string to null 
TStr::TStr() { 
    strPtr = 0; 
    strSize = 0; 
} 
//constructor; conversion from the char string 
TStr::TStr(const char *str) { 
    int i=0; 
    while (str[i] != '/0') { 
     strPtr = new char [strlen(str)+1]; 
     for (i=0; i <strSize;++i) { 
      strPtr[i] = str[i]; 
     } 
     ++i; 
    } 
    strSize = i; 
} 
//Copy constructor 
TStr::TStr(const TStr&) { 
} 
//Destructor 
TStr::~TStr() { 
    if (strPtr) { 
     delete[] strPtr; 
    } 
} 

//subscript operators-checks for range 
char& TStr::operator [] (int i) { 
    assert (i >= 0 && i < strSize); 
    return strPtr[i]; 
} 
const char& TStr::operator [] (int i) const { 
    assert (i >= 0 && i < strSize); 
    return strPtr[i]; 
} 

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    //this->strPtr += str.strPtr; 
    //this->strSize += str.strSize; 
    return *this; 
} 
//overload the assignment operator 
const TStr& TStr::operator = (const TStr& str) { 
    if (this != &str) { 
     delete[] strPtr; 
     strPtr = new char[strSize = str.strSize]; 
     assert(strPtr); 
     for (int i=0; i<strSize; ++i) { 
      strPtr[i] = str.strPtr[i]; 
     } 
    } 
    return *this; 
} 

//overload two relational operators as member functions 
bool TStr::operator == (const TStr& str) const { 
    return (strPtr == str.strPtr && strSize == str.strSize); 
} 
bool TStr::operator < (const TStr& str) const { 
    return (strPtr < str.strPtr && strSize < str.strSize); 
} 
//the length of the string 
int TStr::size() { 
    return strSize; 
} 

お返事ありがとうございました! :)

編集1:さて、コンストラクタは動作していますが、私はまだランタイムエラーが発生しています。私はオーバロードされた+ =演算子を使用することを90%確信しています。それはうまく見え、コンパイルが大丈夫です。私は何が欠けていますか?

(注:だけの小さな変更は上記のコードに行われているが、あなたは全体の多くを見たい場合は私に知らせて)

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    for(int i = 0; i < strSize; ++i) { 
     strPtr[i] += str.strPtr[i]; 
    } 
    return *this; 
} 

EDIT 2:わかりました、私が今持っているものこれ。コンパイルは正常ですが、実際には2つの文字列を+ =と一緒に追加する必要はありません。誰もがアイデアを持っていますか?

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    char *buffer = new char[strSize + str.strSize + 1]; 
    strcpy(buffer, strPtr); 
    strcat(buffer, str.strPtr); 
    delete [] strPtr; 
    strPtr = buffer; 
    return *this; 
} 

//overload the assignment operator 
const TStr& TStr::operator = (const TStr& str) { 
    if (this != &str) { 
     delete[] strPtr; 
     strPtr = new char[strSize = str.strSize]; 
     assert(strPtr); 
     for (int i=0; i<strSize; ++i) { 
      strPtr[i] = str.strPtr[i]; 
     } 
    } 
    return *this; 
} 
+0

これはタイプミスかどうかわかりませんが、NULLターミネータがエスケープ文字ではなくフォワードスラッシュを使用しているようです。 – Dawson

+0

デストラクタで 'if(strPtr)'をチェックする必要はありません。 'delete []' 'NULL'ポインタはnopであり、クラッシュしません。 –

+0

また、リリースビルドでは削除されているので、 'assert'を使用しないでください。例外を使用します。 –

答えて

2

を多くの混乱。

iを2つの異なるものに対して同時に使用します。また、strの内容全体をstrPtrにコピーします。

基本的には、Cランタイムライブラリを使用するかどうかを決定する必要がありますか?それを使用して

TStr::TStr(const char *str) 
{ 
    strSize = strlen(str); 
    strPtr = new char [strSize+1]; 
    strcpy(strPtr, str); 
} 

は、それを使用していない。他の内部

TStr::TStr(const char *str) 
{ 
    int i = 0; 
    while (str[i] != '\0') 
     ++i; 
    strSize = i; 
    strPtr = new char [i+1]; 
    for (i=0; i < strSize;++i) 
     strPtr[i] = str[i]; 
} 
+0

ありがとう!私は講師が常にCタイプの関数を使っていることが悪いと強調しているので、2番目のオプションを使いました.Cランタイムライブラリを避けることができればいいと思います。 – RedFred

+0

forループテストが 'i <= strSize'に変更されると、このコードが' i + 1'のサイズの文字列を割り当てたとしても、このコードが新しい文字列をヌル終了するとは思わない'str'の最後のヌル終了文字は' strPtr'にコピーされますか?または、ヌル終端文字は不要ですか? – Jason

+0

@RedFred:あなたの講師はナットです。また、std libの文字列クラスがあなたにうまく機能しない理由は全くわからないので、タスク全体がかなりダムです。 –

3

は、要約すると:

  • 私は
  • strSizeが初期化されていない使用されている尖ったラインに再初期化され、上記と同じ行に(神が何を知っています)。 strSize = strlen(str)でなければなりません。

    // as James perfectly illustrated 
    TStr::TStr(const char *str) 
    { 
        int i = 0; 
        while (str[i] != '\0') 
         ++i; 
        strSize = i; 
        strPtr = new char [i+1]; 
    
        while (*strPtr++ = *str++); // with a bit of k&R 
    } 
    
    //overload the concatenation oprerator 
    TStr TStr::operator += (const TStr& str) { 
        for(int i = 0; i < strSize; ++i) { 
         strPtr[i] += str.strPtr[i]; 
        } 
        return *this; 
    } 
    

    問題:

    男はそれが

    int i=0; 
    while (str[i] != '\0') { // as Seth pointed out it's '\0' 
        strPtr = new char [strlen(str)+1]; 
        for (i=0; i <strSize;++i) { // i is reinitialized here !!! 
         strPtr[i] = str[i]; 
        } 
        ++i; 
    } 
    strSize = i; 
    

がより建設的には混乱のようなものだと言っていたよう

  • 文字列ターミネーターchracterは
  • 間違っています

    • 文字列を連結したい場合は、両方の文字列をまとめて保持する必要があります。つまり、文字配列を再割り当てする必要があります。そうしないと
    • あなたの文字列のサイズは更新されません。それ?
    • strPtr [i] + = str.strPtr [i];何をここでやっていることは本当に8ビット

    ソリューション(私はそれを向上させることができる絶対に確信しているが、あなたが始める必要があります)に保存されている整数追加された:あなたのctorのはかなりある

    //overload the concatenation oprerator 
    TStr TStr::operator += (const TStr& str) { 
        unsigned int i = 0; 
        while (str.strPtr[i] != '\0') 
         ++i; 
        // allocate the new buffer 
        char* newStr = new char[i + strSize + 1]; 
        // copy the old string 
        unsigned int j = 0; 
        for (; j < strSize; ++j) 
        { 
         newStr[j] = strPtr[j]; 
        } 
        // update the size 
        strSize += i; 
        // release the old buffer 
        delete[] strPtr; 
        // finally concatenate 
        char* copyPtr = newStr + j; 
        while(*copyPtr++ = *(str.strPtr)++); 
        // and swap the pointers 
        strPtr = newStr;  
        return *this; 
        } 
    
  • +0

    また、それは '\ 0''、_not_' '/ 0'' –

    +0

    @セスカーネギーは完全にそれを逃した;私は一目ぼれで私の目に飛び込んだ。補正された。おかげで – celavek

    2

    なぜ二つのループ1?ある文字列から別の文字列に文字をコピーするには、あまりにも難しいと思っています。ここにいくつかのコードがあります

    //constructor; conversion from the char string 
    TStr::TStr(const char *str) { 
        strSize = strlen(str); 
        strPtr = new char [strSize+1]; 
        for (int i=0; i <strSize; ++i) { 
         strPtr[i] = str[i]; 
        } 
        strPtr[strSize] = '\0'; 
    } 
    

    もっと簡単です!

    +0

    James Curranが提案しstrcpyを使用する必要がありますが、ループを正しく書いたかどうかを見せたいと思います。 – john

    +0

    私は同意しません。独自の文字列クラスを作成しているなら、おそらく手で操作する方法を知りたいので、 'strcpy'は簡単な方法で自分自身を短絡しています。 –

    関連する問題