1

bignumber大きな数値を文字列として取り、それを配列に格納するという名前のクラスを実装しました。

operation +2つのbignumbersを追加するための友達を作りました。実行後、プログラムが応答しないというエラーが表示されます。何が問題ですか?

.h ファイル:

class bignumber
{
        private:
            int *number;
            int size;
            string num;
        public:
        bignumber(int);
        bignumber(string ,int);
        ~bignumber();
        friend bignumber operator+(bignumber,bignumber);
};

定義:

bignumber :: bignumber(int numsize)
{
this->size= numsize;
this->number= new int[size];
};

bignumber :: bignumber(string inputnum,int numsize)
{
int *number = new int[numsize];
size = numsize;
num = inputnum;
for(int i=0;i<numsize;i++){
    number[i] = int(num[i])-48;
    };
};

bignumber :: ~bignumber()
{
delete [] number;
};

bignumber operator+(bignumber num1,bignumber num2)
{
if(num2.size>num1.size){
    int e = num2.size - num1.size - 1;
    int *tempnum = new int [num2.size];
    for(int i=0;i<num1.size;i++){
        tempnum[e+i] = num1.number[i];
    }
    delete [] num1.number;
    num1.number = new int[num2.size];
    for(int i=0;i<num2.size;i++){
        num1.number[i] = tempnum[i];
    }
    delete [] tempnum;
}
else if(num1.size>num2.size){
    int e = num1.size - num2.size - 1;
    int *tempnum = new int [num1.size];
    for(int i=0;i<num2.size;i++){
        tempnum[e+i] = num2.number[i];
    }
    delete [] num2.number;
    num2.number = new int[num1.size];
    for(int i=0;i<num1.size;i++){
        num2.number[i] = tempnum[i];
    }
    delete [] tempnum;
}
bignumber temp(max(num1.size,num2.size));
int carry = 0;
for(int i = 0;i < temp.size;i++){
    temp.number[i] = num1.number[i] + num2.number[i] + carry;
    if (temp.number[i] > 10){
        temp.number[i] -= 10;
        int carry = 1;
    }
};
if(carry = 1){
    int *temp2 = new int[temp.size+1];
    temp2[0] = carry;
    for(int j = 1;j < temp.size+1;j++){
        temp2[j] = temp.number[j-1];
    };
    temp.size += 1;
    delete [] temp.number;
    temp.number = new int[temp.size];
    for(int i=0;i<temp.size;i++){
        temp.number[i] = temp2[i];
    }
    delete [] temp2;
};
};

operator >>また、数値を入力するための定義方法もわかりません。友達としてこれを書きましたが、うまくいきません:

istream& operator>>(string s,int size)
{
bignumber(s,size);

};
4

1 に答える 1

2

1)コピーコンストラクターを提供していないため、コンパイラーは浅いコピーでコピーコンストラクターを作成します。同じことが operator= にも当てはまります。手動でメモリを割り当てる場合、これは非常に間違っています。

パラメータを値で渡す operator+ を呼び出すと、オペランドの浅い一時コピーが 2 つ作成されます。次に、これらの一時変数を変更してポインタを削除し、新しい値に設定します。しかし、オペランドはそれについて何も知らないので、それらのnumberポインタは依然として削除されたメモリを指している.

operator+ では何も返さないが、返す必要があり、コピー コンストラクターがないと、別の割り当てエラーが発生します。

2) 複雑なオブジェクトを値で渡すことは、めったに良い習慣ではありません。本当の理由がある場合にのみ行ってください。それ以外の場合は、const myclass& param代わりに使用してください。operator+ の場合、署名は bignumber operator+(const bignumber& num1, const bignumber& num2). はい、num1 と num2 を変更することはできないため、拡大する必要がある数値のローカル コピーが必要ですが、これは 2 つではなく 1 つのコピーです。

3) operator+ の実装は、より単純な実装を既に行っている場合に行うのが最適です。MyClass& MyClass::operator+=(const MyClass& that);その後、次を使用できます。

MyClass operator+(const MyClass& first, const MyClass& second)
  {
  MyClass retval(first);
  retval+=second;
  return retval;
  }

いくつかの重要な機能を提供していないため、operator+ は必要以上に複雑になります。数回サイズを変更しますnumber- メンバー関数にしないのはなぜresize(int newsize)ですか? 個別にテストとデバッグを行うことができます。そうすれば、オペレーターははるかに簡単になります。

...これはすべて明白な質問につながります:なぜあなたはvector<int>数字を使わないのですか? 上記の問題はすべて解決されます。コンパイラによって生成されたコンストラクターと operator= は問題なく動作し、割り当ての悪夢もなくresize()、他の多くの便利な関数が既に提供されており、徹底的にテストされています。または、文字列のみを使用することもできます。int は、それぞれに 0..9 の数字のみを格納するため、実際にはコードで無駄になります。int2character や character2int などのメンバー関数を定義すると、ほとんどの問題が解消されます。

4) ストリームの operator>> には署名が必要です

istream& operator>>(istream& is, bignumber& num);

そのようなものになります:

istream& operator>>(istream& is, bignumber& num)
  {
  string strTmp;
  is>>strTmp;
  //checks for istream state etc
  //...
  //calculate size of number from the extracted string
  //...
  //then construct a temporary
  bignumber tmp(strTmp, calcsize);
  num=tmp;//don't forget assignment operator
  //or
  //just provide a method to reset value of bignumber from string
  //it can be a member function
  num.assign(strTmp);
  //or operator=(const string& str);
  num=strTmp;
  return is;
  }

つまり、通常、ストリーム オペレーターを作成するには、他の型に対して既に定義されているストリーム オペレーターを使用します。

5) キャリー フラグを使用した後、サイクルでキャリー フラグをリセットしません。

于 2013-04-16T08:24:05.103 に答える