1

Тема: C ++. Однонапрямлений список. Перевизначення операторів.

Усім привіт.
Прошу Вас допомогти у вирішенні такого завдання :
я створив клас Довге ціле число , для збереження числа використав лінійний однонапрямлений список .

struct Digit {
        short a;
        Digit *next;
};

class LongDigit {
    Digit *head;
    short len;
public:
    LongDigit();
    LongDigit(char*, short);
    LongDigit(const LongDigit&);
    ~LongDigit();
    LongDigit& operator=(const LongDigit&);
    void input ();
    void print();
    inline friend int GetLen(const LongDigit);
    void ifNULL();
    void normalyze();
    friend LongDigit operator+ (const LongDigit, const LongDigit);
    friend LongDigit operator- (const LongDigit, const LongDigit);
};

LongDigit::LongDigit(){
    head = NULL;
    len = 0;
    cout << "\nConstruktor default\n";
}

LongDigit::LongDigit(char *ch, short n){
    len = n;
    head = new Digit;
    if(len) {
        short tmp;
        Digit *end = head;
        for(int i = 0; i < len; i ++) {
            tmp = ch[i] - '0';
            end->a = tmp;
            if(i != len - 1) {
                end->next = new Digit;
                end = end->next;
            }
        }
        end->next = NULL;
    }
    else {
        head->a = 0;
        head->next = NULL;
    }
    cout << "\nConstructor with parameters\n";
}

LongDigit::LongDigit(const LongDigit &ob) {
    len = ob.len;
    if(len) {
        head = new Digit;
        Digit *end = head;
        Digit *tmp = ob.head;
        for(int i = 0; i < len; i ++) {
            end->a = tmp->a;
            if(i != len - 1) {
                end->next = new Digit;
                end = end->next;
            }
            tmp = tmp->next;
        }
        end->next = NULL;
        }
    else
        head = NULL;
    cout << "copy construktor\n";
}

LongDigit::~LongDigit(){
    if(len) {
        Digit *end = head;
        Digit *tmp;
        while(end) {
            tmp = end->next;
            delete end;
            end = tmp;
        }
        delete head;
        len = 0;
        cout << "\nDestruktor worked\n";
    }
}

LongDigit& LongDigit::operator=(const LongDigit &ob) {
    len = ob.len;

    if(len) {
        Digit *end = head;
        Digit *tmp;
        while(end) {
            tmp = end->next;
            delete end;
            end = tmp;
        }
        delete head;
    /* ********************************************** */
        head = new Digit;
        Digit *h = head;
        end = ob.head;
        do {
            h->a = end->a;
            h->next = new Digit;
            h = h->next;
            end = end->next;
        }
        while(end);
        h = NULL;
    }
    return *this;
}

void LongDigit::input() {
    cout << "Введіть кількість цифр у числі\n";
    cin >> len;
    head = new Digit;

    if(len) {
        cout << "Введіть число\n";
        char *ch = new char[len];
        short tmp;
        cin >> ch;
        Digit *end = head;
        for(int i = 0; i < len; i ++){
            tmp = ch[i] - '0';
            end->a = tmp;
            if(i != len - 1) {
                end->next = new Digit;
                end = end->next;
            }
        }
        end->next = NULL;
        delete ch;
    }
    else {
        head->a = 0;
        head->next = NULL;
    }
}

void LongDigit::print(){
    cout << "\n*** Output ***\n";
    if(len){
        Digit *end = head;
        while(end) {
            cout << end->a;
            end = end->next;
        }
        cout << endl;
    }
    else
        cout << "0\n";
}

void LongDigit::ifNULL() {
    cout << "\n*** If NULL ***\n";

    if(head == NULL)
        cout << "Число дорівнює нулю!\n";
    else if(head->a == 0 && head->next == NULL) {
        cout << "Число дорівнює нулю!\n";
    }
    else
        cout << "Число не дорівнює нулю!\n";
}

int GetLen(LongDigit ob) {
    return ob.len;
}

void LongDigit::normalyze() { // відкидання нулів на початку
    if(len == 0 || len == 1)
        return;
    Digit *end = head;
    short flag = 0;
    for(int i = 0; i < len; i ++) {
        if(end->a == 0){
            end = end->next;
        }
        else{
            flag = 1;
            break;
        }
    }
    if(flag == 1) {
            short count = 0; // лічильник для підрахунку видалених елементів
        for(int i = 0; i < len; i ++) {
            if(head->a == 0) {
                end = head->next;
                delete head;
                head = end;
                count ++;
                if(head->a != 0)
                    break;
            }
        }
        len -= count; // становлення правильного розміру числа після видалення нулів
    }
    else {
        Digit *tmp;
        end = head->next;
        while (end != NULL){
            tmp = end->next;
            delete end;
            end = tmp;
        }
        head->next = NULL;
        delete tmp;
        len = 1;
    }
}

Тобто число розбите по розрядах.
І тепер мені потрібно перевизначити оператор додавання для цього класу, а як це зробити - важко собі уявляю, тому надіюсь на Вашу допомогу.

2

Re: C ++. Однонапрямлений список. Перевизначення операторів.

Ви вкрай невдало вибрали структуру для збереження інформації.
По суті: вам треба взяти останні елементи двох списків, скласти їхні значення, записати результат (за модулем 10) в останній елемент нового списку. Потім взяти ПЕРЕДостанні елементи... ви вже побачили проблему?

Подякували: leofun011

3

Re: C ++. Однонапрямлений список. Перевизначення операторів.

koala написав:

Ви вкрай невдало вибрали структуру для збереження інформації.
По суті: вам треба взяти останні елементи двох списків, скласти їхні значення, записати результат (за модулем 10) в останній елемент нового списку. Потім взяти ПЕРЕДостанні елементи... ви вже побачили проблему?

А якщо ревеснути список, а новий розряд добавляти в голову?..

4

Re: C ++. Однонапрямлений список. Перевизначення операторів.

Arete написав:
koala написав:

Ви вкрай невдало вибрали структуру для збереження інформації.
По суті: вам треба взяти останні елементи двох списків, скласти їхні значення, записати результат (за модулем 10) в останній елемент нового списку. Потім взяти ПЕРЕДостанні елементи... ви вже побачили проблему?

А якщо ревеснути список, а новий розряд добавляти в голову?..

Тоді матимете головний біль із виведенням.
Втім, здається, (відносно) прийнятний вихід таки є: рекурсивна функція, що приймає чотири параметри: два Digit та дві довжини "хвостів". Ну і п'ятий - результат. Поки хвости не зрівняються - сумується тільки один доданок.

5

Re: C ++. Однонапрямлений список. Перевизначення операторів.

koala написав:

Ви вкрай невдало вибрали структуру для збереження інформації.
По суті: вам треба взяти останні елементи двох списків, скласти їхні значення, записати результат (за модулем 10) в останній елемент нового списку. Потім взяти ПЕРЕДостанні елементи... ви вже побачили проблему?

я дійду до останього елементу у списку, але потім повернутись назад не зможу ж, оскільки в мене однонапрямлений список.

а повернутись назад мені потрібно в будь-якому випадку.
як би це обійти, крім двозв'язного списку?

6

Re: C ++. Однонапрямлений список. Перевизначення операторів.

вже не актуально.
Списки переписав в масиви.
І на масивах реалізував додавання, проходом з кінця на початок.
Усім дякую )