Переполнение Стека При Перегрузке Операторов

Тема в разделе "Общие вопросы по С и С++", создана пользователем Ytsukene, 24 май 2014.

  1. Ytsukene

    Ytsukene New Member

    Регистрация:
    24 май 2014
    Сообщения:
    1
    Симпатии:
    0
    Задача - создать класс рациональной дроби - Rational -, числитель и знаменатель которой - массивы типа unsigned char фиксированного размера. Определить операции сложения, вычитания, умножения, деления и сравнений (>,<,==). Я решил создать вспомогательный класс safeunschar и в нём определить сложение, вычитание и умножение массивов. Потом, на основе этих операций, я определил по заданию действия с дробями.
    Проблема в том, что для удобства, операции с массивами могут вызываться из других операций - например, операция вычитания в моём исполнении вычитает только из большего меньшее, иначе вызывается операция вычитания, в которой они меняются местами. Или для сравнения используется операция вычитания между массивами, и по знаку операции возвращается значение. А так как при таких вызовах из операций создаются всё новые и новые объекты в стеке - стек полностью ими выжирается, и программа вылетает.
    Пожалуйста, подскажите, как реорганизовать программу, чтобы сэкономит память.


    Код (C++):
    #define _CRT_SECURE_NO_WARNINGS //отключает запрещение компиллятора использовать небезопасные функции по типу strcat(), strcpy, itoa() и т. д.
    #include <iostream>
    #include <string>

    using namespace std;

    void itounchar(int value, unsigned char* buf)
    {
    int size = 0, b = value;
    do{ b /= 10; size++; } while (b != 0); //подсчитывается размер числа
    buf[size] = '\0';  //на конец числа в массиве ставится нуль-символ
    for (size -= 1; size >= 0; size--) //число "задом наперёд" записывается в массив
    {
    buf[size] = static_cast<char>(value % 10 + 48); //записывается последняя цифра числа (прибавляется 48, так как кодировки int и char различаются на 48)
    value /= 10;    //последняя цифра числа стирается
    }
    }

    class safeunschar
    {
    int minus;
    static const int fixsize = 100; //static - в любом объекте этого класса size будет равно 100
    unsigned char *arr;
    int size;
    void check()
    {
    int begzero = 0;
    bool check = true;
    for (int i = 0; i < size; i++)
    {
    if (arr[i] != '0')
    check = false;
    if (check) begzero++;
    }
    if (check)
    {
    size = 1;
    minus = 1;
    }
    else if (begzero > 0)
    {
    for (int a = 0, b = begzero; b < size; b++, a++)
    arr[a] = arr[b];
    size -= begzero;
    }

    }
    void reverse()
    {
    unsigned char buf;
    for (int a = 0, b = size - 1; a < b; a++, b--)
    {
    buf = arr[a];
    arr[a] = arr[b];
    arr[b] = buf;
    }
    }
    public:
    safeunschar()
    {
    minus = 1;
    arr = new unsigned char[fixsize];
    arr[0] = '0';
    size = 1;
    }
    safeunschar(safeunschar& ob)
    {
    //cout << "COPY!" << endl;
    minus = ob.minus;
    arr = new unsigned char[fixsize];
    for (int i = 0; i < ob.size; i++)
    arr[i] = ob.arr[i];
    //cout << arr << endl;
    size = ob.size;
    }
    safeunschar operator*(int a)
    {
    safeunschar buf;
    if (a < 0)
    {
    buf.minus = -1;
    a *= (-1);
    }

    int high = 0, b;

    //cout << "\t\t\t" << endl;//Отладка!
    //cout << "\t\t\t" << "Считаем "; this->show(); cout << "\t\t\t   * "<<a<<endl;

    for (int i = 0, th = this->size - 1; th >= 0; i++, th--)
    {
    //cout << "\t\t\tДействие " << i << endl;//Отладка!
    b = static_cast<int>(this->arr[th] - 48) * a + high;
    //cout << "\t\t\t" << "b = " << b << endl;//Отладка!
    if (b >= 10)
    {
    buf.arr[i] = static_cast<char>(b % 10 + 48);
    high = b / 10;
    }
    else
    {
    buf.arr[i] = static_cast<char>(b + 48);
    high = 0;
    }
    //cout << "\t\t\t" << arr[th] << " * " << a << " = " << buf.arr[i] << endl;//Отладка!
    //cout << "\t\t\t" << "high = " << high << endl;//Отладка!
    if (i > 0) buf.size++;
    }
    if (high > 0)
    {
    /*cout << "\t\t\tВдобавок:" << endl;*/
    for (int i = buf.size; high > 0; i++, high /= 10)
    {
    buf.arr[i] = static_cast<char>(high % 10 + 48);
    /*cout << "\t\t\t" << arr[i] << endl;
    cout << "\t\t\thigh = " << high / 10 << endl;*/

    buf.size++;
    }
    }
    //cout << "неповёрнутый: "; buf.show();
    buf.reverse();
    //cout << "повёрнутый: "; buf.show();
    buf.check();
    //cout << "отредактированный: "; buf.show();

    return buf;
    }
    safeunschar operator+(safeunschar& op)
    {
    safeunschar buf;
    int high = 0, b;

    if (this->minus == -1 && op.minus == -1) buf.minus = -1;
    else if (this->minus == -1)
    {
    buf = (op - *this*(-1));
    return buf;
    }
    else if (op.minus == -1)
    {
    buf = (*this - op*(-1));
    return buf;
    }

    // cout << '\t' << endl;//Отладка!
    // cout << "\t\t" << "Считаем "; this->show(); cout << "\t\t  + "; op.show();
    if (this->size < op.size)
    {
    buf = (op + (*this));  //предполагается, что первый операнд больше, в противном случае они меняются местами
    return buf;
    }

    for (int i = 0, th = this->size - 1, o = op.size - 1; th >= 0; i++, th--, o--)
    {
    // cout << "\t\tДействие " << i << endl;//Отладка!
    if (o < 0)
    b = static_cast<int>(this->arr[th]) - 48 + high;
    else
    b = static_cast<int>(this->arr[th]) - 48 + static_cast<int>(op.arr[o]) - 48 + high;
    //cout << "\t\t" << "b = " << b << endl;//Отладка!
    if (b >= 10)
    {
    buf.arr[i] = static_cast<char>(b % 10 + 48);
    high = b / 10;
    }
    else
    {
    buf.arr[i] = static_cast<char>(b + 48);
    high = 0;
    }
    //cout << "\t\t" << arr[th] << " + " << op.arr[o] << " = " << buf.arr[i] << endl;//Отладка!
    //cout << "\t\t" << "high = " << high << endl;//Отладка!
    if (i > 0) buf.size++;
    }

    if (high > 0)
    {
    //cout << "\t\t\tВдобавок:" << endl;
    for (int i = buf.size; high > 0; i++, high /= 10)
    {
    buf.arr[i] = static_cast<char>(high % 10 + 48);
    //cout << "\t\tновый = " << buf.arr[i] << endl;
    //cout << "\t\t\thigh = " << high / 10 << endl;
    buf.size++;
    }
    }

    //cout << "неповёрнутый: "; buf.show();
    buf.reverse();
    //cout << "повёрнутый: "; buf.show();
    buf.check();
    //cout << "отредактированный: "; buf.show();
    return buf;
    }
    safeunschar operator-(safeunschar& op)
    {
    safeunschar buf;
    int c, d, c_next;

    if (this->minus == -1 && op.minus == -1)
    {
    buf = (op*(-1) - *this*(-1));
    return buf;
    }
    else if (this->minus == -1)
    {
    buf = ((op + *this*(-1))*(-1));
    return buf;
    }
    else if (op.minus == -1)
    {
    buf = (*this + op*(-1));
    return buf;
    }

    if (this->size < op.size || this->size == op.size)
    {
    bool flag = false;
    for (int i = 0; i < size; i++)
    {
    if (this->arr[i] < op.arr[i])
    flag = true;
    }
    if (flag)
    {
    buf = (op - *this);
    buf = buf*(-1);
    return buf;
    }
    }

    // cout << '\t' << endl;//Отладка!
    // cout << "\t" << "Считаем "; this->show(); cout << " - "; op.show(); cout << endl;//Отладка!

    c = static_cast<int>(this->arr[this->size - 1]) - 48;

    for (int i = 0, th = this->size - 1, o = op.size - 1; th >= 0; i++, th--, o--)
    {
    if (th != 0)
    c_next = static_cast<int>(this->arr[th - 1]) - 48;
    if (o >= 0)
    d = static_cast<int>(op.arr[o]) - 48;
    else
    d = 0;
    //cout << "Действие " << i << endl;//Отладка!


    if (c < d)
    {
    c_next--;
    c += 10;
    }
    //cout << "\t" << "c = " << c << endl;//Отладка!
    //cout << "\t" << "d = " << d << endl;//Отладка!
    buf.arr[i] = static_cast<char>(c - d) + 48;

    c = c_next;
    // cout << "\t" << arr[th] << " - " << op.arr[o] << " = " << buf.arr[i] << endl;//Отладка!
    if (i > 0) buf.size++;
    }
    //cout << "неповёрнутый: "; buf.show();
    buf.reverse();
    //cout << "повёрнутый: "; buf.show();
    buf.check();
    //cout << "отредактированный: "; buf.show();
    return buf;
    }
    safeunschar operator*(safeunschar& op)
    {
    safeunschar buf, sum;
    int index = this->minus;

    if (this->size < op.size)
    return buf = (op*(*this));

    //cout << "\tПереданы параметры:" << "\n\ta = "; this->show(); cout << "\n\tb = "; op.show();
    for (int o = op.size - 1, th = this->size, i = 0; o >= 0 && th >= 0; o--, th--, i++)
    {
    //cout << "\tдействие " << i << ". buf = "; buf.show();
    //cout << "\tУмножаем " << static_cast<int>(op.arr[o] - 48) * static_cast<int>(pow(10,i)) << " на "; this->show();
    //buf = buf + (*this*(index)) * (static_cast<int>(op.arr[o] - 48) * static_cast<int>(pow(10, i)));
    sum = (*this*(index)) * (static_cast<int>(op.arr[o] - 48));
    for (int j = 0, k = sum.size; j < i; j++, k++)
    {
    sum.arr[k] = '0';
    sum.size++;
    }
    buf = buf + sum;
    }
    if (this->minus == -1 && op.minus == -1)
    buf.minus = 1;
    else if (this->minus == -1 || op.minus == -1)
    buf.minus = -1;
    else
    buf.minus = 1;
    buf.check();
    return buf;
    }

    bool operator==(char* s)
    {
    int sis;
    for (sis = 0; s[sis] != '\0'; sis++);
    if (sis != size)
    return false;
    else
    {
    for (int i = 0; i < size; i++)
    {
    if (arr[i] != (char)s[i])
    return false;
    else
    return true;
    }
    }
    }
    bool operator<(safeunschar& op)
    {
    safeunschar buf = *this - op;
    if (buf.minus > 0 || buf == "0")
    return false;
    else
    return true;
    }
    bool operator>(safeunschar& op)
    {
    safeunschar buf = op - *this;
    if (buf.minus > 0 || buf == "0")
    return false;
    else
    return true;
    }

    bool read(string s) //Чтение с клавиатуры
    {
    //cout << "/tstring: " << s << endl;
    if (s.at(0) == '0' && s.length() > 1) return false;
    for (int i = 0; i < s.length(); i++)
    {
    if (((s.at(i)<'0') || (s.at(i)>'9')) && s.at(i) != '-')
    return false;
    }

    if (s.at(0) == '-')
    {
    minus = -1;
    s.erase(0, 1);
    }
    else
    minus = 1;
    int n = 0;
    for (int i = 0; i < s.length(); i++)
    {
    arr[n] = (int)s.at(i);
    n++;
    }
    size = n;
    return true;
    }
    void show()
    {
    //cout << "\n\t size = " << size << "\n";
    if (minus == -1)cout << '-';
    for (int i = 0; i < size; i++)
    cout << arr[i];
    }
    };


    class Rational
    {
    safeunschar numerator;
    safeunschar denomenator;

    //void reduce()
    //{
    // if (!strcmp((char*)numerator, "0")) return;
    // int first, second, reduce;
    // first = atoi((char*)numerator); //присвоение числителя
    // second = atoi((char*)denominator);//присвоениее знаменателя

    // while (first != 0 && second != 0)  //цикл вычисления наименьшего общего кратного
    // {
    //   if (first >= second) first %= second;
    //   else second %= first;
    // }
    // reduce = first + second; //reduce - итоговое наименьшее общее кратное
    //
    // itounchar(atoi((char*)numerator) / reduce, numerator);
    // itounchar(atoi((char*)denominator) / reduce, denominator);
    //}
    public :

    Rational()
    {
    //числитель и знаменатель инициализируются автоматически
    }
    void read ()    //Чтение с клавиатуры
    {
    string s1,s2;
    do {
    cout << "Введите числитель: " << endl;
    getline(cin,s1);
    cout << "Введите знаменатель: " << endl;
    getline(cin,s2);
    } while ((!numerator.read(s1) || !denomenator.read(s2)) && cout << "Неправильный ввод!" << endl);
    }

    bool read(string s1,string s2)
    {
    if (!numerator.read(s1) || !denomenator.read(s2))
    return false;
    else
    return true;
    }

    void show()
    {
    numerator.show(); cout << " / "; denomenator.show(); cout << endl;
    }

    Rational(Rational& ob)
    {
    this->numerator = ob.numerator;
    this->denomenator = ob.denomenator;
    }
    Rational operator+(Rational op) // op - второй операнд сложения (первый передаётся неявно)
    {
    Rational buf;

    buf.numerator = this->numerator*op.denomenator + op.numerator*this->denomenator;
    buf.denomenator = this->numerator*op.denomenator;

    return buf;
    }
    Rational operator-(Rational op)
    {
    Rational buf;

    buf.numerator = this->numerator*op.denomenator - op.numerator*this->denomenator;
    buf.denomenator = this->numerator*op.denomenator;

    return buf;
    }
    Rational operator*(Rational op)
    {
    Rational buf;

    buf.numerator = this->numerator*op.numerator;
    buf.denomenator = this->numerator*op.denomenator;

    return buf;
    }
    Rational operator/(Rational op)
    {
    Rational buf;  //Результат сложения
    if (op.numerator == "0")
    {
    cout << "Деление на ноль!";
    return *this;
    }

    buf.numerator = this->numerator*op.denomenator;
    buf.denomenator = op.numerator*this->denomenator;

    return buf;
    }
    bool operator>(Rational op)
    {
    if (this->numerator*op.denomenator > op.numerator*this->denomenator)
    return true;
    else
    return false;
    }
    bool operator<(Rational op)
    {
    if (this->numerator*op.denomenator < op.numerator*this->denomenator)
    return true;
    else
    return false;
    }
    /*bool operator==(Rational op)
    {
    if (this->minus*atoi((char*)this->numerator)*atoi((char*)op.denominator) == op.minus*atoi((char*)op.numerator)*atoi((char*)this->denominator))
    return true;
    else
    return false;
    }*/


    };

    int main()
    {
    setlocale(0,"rus");
    Rational a,b;

    string s1, s2;
    s1 = "732195927564";
    s2 = "151784321267";
    a.read(s1,s2);
    cout << "a = "; a.show();
    s1 = "562736912";
    s2 = "115921101";
    b.read(s1,s2);
    cout << "b = "; b.show();


    cout << "a+b = "; (a + b).show();
    cout << "a-b = "; (a - b).show();
    cout << "a*b = "; (a*b).show();
    cout << "a/b = "; (a / b).show();
    if (a > b) cout << "a>b" << endl;
    else if (a < b) cout << "a<b" << endl;
    else cout << "a=b" << endl;

    system("pause");
    return 0;
    }
     
Загрузка...
Похожие Темы - Переполнение Стека При
  1. Ruslan280
    Ответов:
    9
    Просмотров:
    782
  2. susinmn
    Ответов:
    6
    Просмотров:
    3.710
  3. Tamchik
    Ответов:
    2
    Просмотров:
    4.582

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