Перегрузка Операторов

XADD

New member
11.09.2011
2
0
#1
Перегрузил операцию сложения двух двоичных чисел но оно работает частично
Например если присвоить s1=111,s2=111, то s3=s1+s2=1110(вроде бы верно), далее пишу s3+s1=(1110+111) программа выдает s3=111 хотя должно быть 10101. Дебагом пользовался но не могу понять что не работает.

C++:
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
class Stroka
{
private:
char *String;
int SizeOfString;
public:
Stroka() {}
Stroka(const char *inString)
{
String = new char[strlen(inString)];
if (inString!=0) strcpy(String,inString);
cout << "String constructor" << endl;
}
Stroka(char ch)
{
String=new char[strlen(&ch)];
if (ch!=0) strcpy(String,&ch);
cout << "Symbol constructor" << endl;
}
Stroka (const Stroka& copy)
{
copy.String;
cout << "Copy constructor" << endl;
}
void GetClear ()
{
String="\0";
}
int GetLength ()
{
SizeOfString=strlen(String);
cout << SizeOfString << endl;
return SizeOfString;
}
void Show ()
{
cout << String << endl;
}
};
class BitStroka
{
private:
char *BitString;
int SizeOfBitString;
int Value;
public:
////-------------------
BitStroka() {BitString = new char[10]; SizeOfBitString=0; Value=0;}
////---------------------
//BitStroka(const BitStroka&);
BitStroka(const char *InBitString)
{
int iterator=0;
for (int i=0; i<strlen(InBitString);i++)
{
if (InBitString[i]=='0' || InBitString[i]=='1') {iterator++;}
if (iterator==strlen(InBitString)) 
{
BitString = new char[strlen(InBitString)];
strcpy(BitString,InBitString);
SizeOfBitString=strlen(InBitString);
Value=atoi(InBitString);
}
}
}

friend BitStroka& operator+(const BitStroka &op1, const BitStroka &op2)
{

BitStroka temp;
int *temp1;
int *temp2;
int *temp3;

if (op1.SizeOfBitString<op2.SizeOfBitString) 
{
temp1 = new int[(op2.SizeOfBitString+1)];
temp2 = new int[(op2.SizeOfBitString+1)];
temp3 = new int[(op2.SizeOfBitString+1)];
for (int i=0;i<(op2.SizeOfBitString+1);i++)
{
temp1[i]=0;
temp2[i]=0;
}
for (int i=0;i<op1.SizeOfBitString;i++)
{
temp1[i+(op2.SizeOfBitString+1-op1.SizeOfBitString)]=op1.BitString[i]-'0';
}
for (int i=0;i<op2.SizeOfBitString;i++)
{
temp2[i+1]=op2.BitString[i]-'0';
}
int carry=0;
int temp4=0;
for (int i=op2.SizeOfBitString;i>=0;i--)
{
temp4=temp1[i]+temp2[i]+carry;
if (temp4>=2) {temp3[i]=temp4-2; carry=1;}
else {temp3[i]=temp4; carry=0;}
}
int j=0;
int k=1;
for (int i=op2.SizeOfBitString;i>=0;i--)
{
j+=temp3[i]*pow(10.0,k-1);
k++;
}
temp.Value=j;
cout << "First" << endl;
} 
else 
{
temp1 = new int[(op1.SizeOfBitString+1)];
temp2 = new int[(op1.SizeOfBitString+1)];
temp3 = new int[(op1.SizeOfBitString+1)];
for (int i=0;i<(op1.SizeOfBitString+1);i++)
{
temp1[i]=0;
temp2[i]=0;
temp3[i]=0;
}
for (int i=0;i<op2.SizeOfBitString;i++)
{
temp1[i+(op1.SizeOfBitString+1-op2.SizeOfBitString)]=op2.BitString[i]-'0';
}
for (int i =0;i<op1.SizeOfBitString;i++)
{
temp2[i+1]=op1.BitString[i]-'0';
}
int carry=0;
int temp4=0;
for (int i=op1.SizeOfBitString;i>=0;i--)
{
temp4=temp1[i]+temp2[i]+carry;
if (temp4>=2) {temp3[i]=temp4-2; carry=1;}
else {temp3[i]=temp4; carry=0;}
}
int j=0;
int k=1;
for (int i=op1.SizeOfBitString;i>=0;i--)
{
j+=temp3[i]*pow(10.0,k-1);
k++;
}
temp.Value=j;

cout << "Second" << endl;
}

return temp;
}
bool operator== (const BitStroka &op1)// Перегрузка функции сравнения
{
if (op1.Value==Value)
{
return true;
} 
else 
{
return false;
}
}
BitStroka& operator +=(const BitStroka &op1)//Функция присвоения
{
SizeOfBitString=op1.SizeOfBitString;
Value=op1.Value;
return *this;
}
void Show()
{
cout << Value << endl;
}
};
int main()
{
BitStroka s1("111");
BitStroka s2("111");
BitStroka s3("111");
s3=(s1+s2);
s3=(s3+s1);
s3.Show();
return 0;
}
 
R

rrrFer

#2
не буду смотреть твой код. приведу фрагмент своего(чтобы не путался в полях):
описание класса:
Код:
struct node{
char c;
node *l,*r;
};
class String{
node *head,*end;
void clear();				//очистка строки
void add(char c);
public:
~String(){
clear();
};
String(){
end=head=0;
};
friend istream& operator >>(istream& in,String& C);
friend ostream& operator <<(ostream&out,String& C);
bool operator > (const String &C);
bool operator < (const String &C);
bool operator == (const String &C);
String& operator = (String& C);
String& String::operator * (String &C);
String& String::operator + (String &C);
};
тебя интересует только оператор сложения
Код:
String& String::operator + (String &C){
node *p,*pt;
String *newString;			//новая строка(которая получится при умножении
newString=new String;
//просматривать списки будем от головы, в сторону увеличения весов разрядов
if(C.end&&this->end){		//проверил валидность концов
p=C.head;				//временный указатель ставлю на голову
pt=this->head;			
do{						//цикл пока список не кочится
if(!p&&!pt)			//числа одинаковой разрядности кончились
return *newString;
if(!p||!pt)			//если один операнд кончился то умножение закончилось
break;			//выходим из цикла
if(p->c=='1')		//собственно умножение
newString->add('1');//воводим 1 
else				
newString->add(pt->c);//выводим в поток один из операндов, если второй единица
p=p->l;				//перешел на следующий узел
pt=pt->l;			//перешел на следующий узел
}while(1);				//тут проверяется валидность указателя, 
if(pt)					//дальше работаем с указателем p
p=pt;				//поэтому если валиден другой то перемещаем p
do{
newString->add(p->c);//добавляю разряд в новую строку
p=p->l;				//перехожу на следующий узел
}while(p);				//продолжается это пока действителен указатель
}
return *newString;
}
void String::add(char c){
node *p=new node;
p->c=c;
if(!head){					//список не был создан
p=new node;	
p->l=0;
p->r=0;					//у первого узла оба указателя нулевые
p->c=c;
end=head=p;				//голова=хвосту=новый узел
}
else{
head->r=p;				//голова ссылается на новый узел
p->r=0;					//а праввый указатель новго узла невалиден
p->l=head;				//ссылка на голову у нового узла слева
head=p;					//добавление в список
}
}
этот код вроде бы работает, если нет - пиши ))
И да, я знаю, что он не лучшим образом написан - писал когда в вузе учился...

Добавлено: комментарии какие-то левые ))
 

XADD

New member
11.09.2011
2
0
#4
Вообщем переписал по другому
C++:
#include <iostream>
#include <cmath>
#include <math.h>
#include <bitset>
#include <iostream>
#include <cmath>
#include <string>
using namespace std;class BitStroka
{
private:
char *BitString;
int SizeOfBitString;
string SValue;
public:
BitStroka() {}

BitStroka(const char *InBitString)
{
int iterator=0;
for (int i=0; i<strlen(InBitString);i++)
{
if (InBitString[i]=='0' || InBitString[i]=='1') {iterator++;}
if (iterator==strlen(InBitString)) 
{
BitString = new char[strlen(InBitString)];
strcpy(BitString,InBitString);
SizeOfBitString=strlen(InBitString);
SValue=InBitString;
}
}
}
friend BitStroka operator+(const BitStroka &op1, const BitStroka &op2)
{
BitStroka temp;
bitset <8>First(op1.SValue);
bitset <8>Second(op2.SValue);
bitset <8>result;
result = First.to_ulong() + Second.to_ulong();
temp.SValue=result.to_string<char,char_traits<char>,allocator<char> >();
cout << result << endl;
return temp;
}
BitStroka& operator = (const BitStroka &op1)
{
SizeOfBitString=op1.SizeOfBitString;
SValue=op1.SValue;
return *this;
}
void show ()
{
cout << SValue << endl;
}
};
void main()
{
BitStroka s1("111");
BitStroka s2("111");
BitStroka s3;
s3=s1+s1;
s3.show();
s3=s1+s3;
s3.show();

}
Подскажите каким образом можно убрать вывод незначащих нулей перед числом, выводит например 0000111 а надо 111. Может есть какой-то элегантный метод?
 
R

rrrFer

#5
извиняюсь, код который я привел... там оператор + - это поразрядная дизъюнкция, походу.
выводит например 0000111 а надо 111. Может есть какой-то элегантный метод?
в вывод вставь что-то типа
Код:
while( a[ i ] == '0' ) i ++;
//а потом вывод, как сейчас
Добавлено: что такое BitString у тебя в классе? - вроде бы хранит невалидный указатель(в примере у s3)

Добавлено: потому что при присваивании BitString не инициализируется:
Код:
	BitStroka& operator = (const BitStroka &op1)
{
SizeOfBitString=op1.SizeOfBitString;
SValue=op1.SValue;
return *this;
}
 
R

rrrFer

#6
не лучший вариант:
Код:
 void show ()
{
int i, n;
n = SValue .size();
for( i = 0; i < n; i ++ )
if( SValue[ i ] != '0' )
break;

cout << &SValue[ i ] << endl;
}
но перепиши свой код, плохо когда поля дублируют друг друга.
 

XADD

New member
11.09.2011
2
0
#7
Спасибо. s3 хранит инвалидный указатель из за конструктора
C++:
BitStroka() {}
без параметров.
 

Stashevckiy

Well-known member
23.10.2011
56
0
#8
Перегрузил операцию сложения двух двоичных чисел но оно работает частично
Например если присвоить s1=111,s2=111, то s3=s1+s2=1110(вроде бы верно), далее пишу s3+s1=(1110+111) программа выдает s3=111 хотя должно быть 10101. Дебагом пользовался но не могу понять что не работает.
Так как знаком с программированием на VHDL и Verilog не понаслышке, то могу тебе сказать, дружище, что может быть не в программе ошибка, а в твоем задании переменных. В принципе, все операции над двоичными числами выполняются при приведением их к одному размеру. По - этому, я бы советовал тебе, когда ты хочешь сложить, как ты писал, 1110 + 111, то писать так -> 1110 + 0111...

P.S. Ну, а может я и не прав, точно не знаю, как компилятор в С++ воспримет такое задание, хотя, если бинарный тип переменных, то все должно быть норм.. :please:
 

Stashevckiy

Well-known member
23.10.2011
56
0
#10
Так как знаком с программированием на VHDL и Verilog не понаслышке, то могу тебе сказать, дружище, что может быть не в программе ошибка, а в твоем задании переменных. В принципе, все операции над двоичными числами выполняются при приведением их к одному размеру. По - этому, я бы советовал тебе, когда ты хочешь сложить, как ты писал, 1110 + 111, то писать так -> 1110 + 0111...

P.S. Ну, а может я и не прав, точно не знаю, как компилятор в С++ воспримет такое задание, хотя, если бинарный тип переменных, то все должно быть норм..
Я тут проглядел код программы, и заметил, что используется тип данных строковый, а исходя из этого выше изложенное мое сообщение тебе помочь ничем не сможет( т.к. оно касается типа bit ).

поясни, особенно это:
r04, я тебе по с++ компилятору вряд ли что-то точно скажу, как я и писал выше, у меня не так много опыта работы с ним, но могу тебе сказать , что в компиляторе для VHDL в Active - HDL ( Active - HDL - это среда разработки на языках описания аппаратуры ) автоматически при 'сборке' происходит приведение размеров операндов при выполнении арифметических операций ( встроенных ). Т.е., если ты хочешь перемножить, к примеру A = 1101 и B = 100100, то компилятор преобразует число А в 001101. Это "опасное" свойство, если о нем не знать, и прогать, не обращая на это внимание.
Извиняюсь, если ни чем не помог.. :)