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

Тема в разделе "C/C++/C#", создана пользователем XADD, 23 окт 2011.

  1. XADD

    XADD New Member

    Регистрация:
    11 сен 2011
    Сообщения:
    2
    Симпатии:
    0
    Перегрузил операцию сложения двух двоичных чисел но оно работает частично
    Например если присвоить 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;
    }
     
  2. rrrFer

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    не буду смотреть твой код. приведу фрагмент своего(чтобы не путался в полях):
    описание класса:
    Код (Text):
    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);
    };
    тебя интересует только оператор сложения
    Код (Text):
    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;                 //добавление в список
    }
    }
    этот код вроде бы работает, если нет - пиши ))
    И да, я знаю, что он не лучшим образом написан - писал когда в вузе учился...

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

    lazybiz Well-Known Member
    C\C++ Team

    Регистрация:
    3 ноя 2010
    Сообщения:
    1.344
    Симпатии:
    0
    левый комментарий
     
  4. XADD

    XADD New Member

    Регистрация:
    11 сен 2011
    Сообщения:
    2
    Симпатии:
    0
    Вообщем переписал по другому
    Код (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. Может есть какой-то элегантный метод?
     
  5. rrrFer

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    извиняюсь, код который я привел... там оператор + - это поразрядная дизъюнкция, походу.
    в вывод вставь что-то типа
    Код (Text):
    while( a[ i ] == '0' ) i ++;
    //а потом вывод, как сейчас
    Добавлено: что такое BitString у тебя в классе? - вроде бы хранит невалидный указатель(в примере у s3)

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

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    не лучший вариант:
    Код (Text):
     void show ()
    {
    int i, n;
    n = SValue .size();
    for( i = 0; i < n; i ++ )
    if( SValue[ i ] != '0' )
    break;

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

    XADD New Member

    Регистрация:
    11 сен 2011
    Сообщения:
    2
    Симпатии:
    0
    Спасибо. s3 хранит инвалидный указатель из за конструктора
    Код (C++):
    BitStroka() {}
    без параметров.
     
  8. Stashevckiy

    Stashevckiy Well-Known Member

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

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

    rrrFer Well-Known Member
    Команда форума C\C++ Team

    Регистрация:
    6 сен 2011
    Сообщения:
    1.324
    Симпатии:
    36
    Stashevckiy
    поясни, особенно это:
     
  10. Stashevckiy

    Stashevckiy Well-Known Member

    Регистрация:
    23 окт 2011
    Сообщения:
    56
    Симпатии:
    0
    Я тут проглядел код программы, и заметил, что используется тип данных строковый, а исходя из этого выше изложенное мое сообщение тебе помочь ничем не сможет( т.к. оно касается типа bit ).

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

Поделиться этой страницей