Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Функция-член не возвращает результат (?) 
V
    Опции темы
FlySabaka
Дата 8.10.2010, 11:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



Здравствуйте!
В качестве упражнения создаю класс "больших чисел". Элементы класса: массив из 40 "цифр", знак, и длина числа. Начал реализовывать сложение двух чисел с одинаковым знаком. Реализация верная: если вставить код функции в main.cpp выдает верный ответ. Но функция addHugiInteger работает неверно. При дебаге в этой функции в списке Local variables вижу предупреждение warnind: can't find linker symbol for virtual table for HugeInteger value (см. HugeInteger.cpp строка 85). Работаю в Code::Blocks с компилятором по-умолчанию (GNU GCC compiler).
Подскажите, что же я делаю не так?
HugeInteger.h
Код

#ifndef HUGEINTEGER_H
#define HUGEINTEGER_H

#define NUM_LENGTH 40

class HugeInteger
{
    public:
        /** Default constructor */
        HugeInteger();
        /** Default destructor */
        virtual ~HugeInteger();
        /** Assignment operator */
        HugeInteger& operator=(const HugeInteger& other);

        void setValue(const char *); // на вход число в виде строки
        void printValue(); // вывод "большого числа" на экран
        int getDigit(int) const; // получить цифру числа. нумерация цифр как в обычном массиве
        int getSign() const; // получить знак числа
        int getLengthOfNumber() const; // получить длину числа
        void setDigit(int i, int j); // установить i - ую цифру равной j
        HugeInteger addHugeInteger(HugeInteger const &other); // к данному числу прибавить other
        
    protected:
    private:
        int digits[NUM_LENGTH]; // массив цифр числа, включая нули слева от других цифр числа
        int number_length; // длина числа, без нулей слева
        int sign; // знак числа
        bool isValidString(const char *) const; // функция проверки входной строки на валидность
        void strPrepare(const char *, char *) const; // функция удаляет из входной строки ненужные нули слева
};

#endif // HUGEINTEGER_H



HugeInteger.cpp
Код

#include "..\include\HugeInteger.h"
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <conio.h>

HugeInteger::HugeInteger()
{
    setValue("+0");
}
HugeInteger::~HugeInteger()
{
}

HugeInteger& HugeInteger::operator=(const HugeInteger& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}

bool HugeInteger::isValidString(const char *str) const // str должна состоять лишь из знака числа и цифр.
{
 ... // здесь все ок
}

void HugeInteger::strPrepare(const char *str, char *new_str) const // удаляем из строки лишние нули слева от ненулевых цифр
{
  ... // здесь все ок
}

void HugeInteger::setValue(const char *str) // задаём числу значение, записанное в строку str.
{
 ... // здесь все ок
}

void HugeInteger::setDigit(int i, int j) // i-ой цифре числа присваиваем j
{
    if (j < 0 || j > 9)
    {
        return;
    }
    digits[i] = j;
    if (j == 0 && i == NUM_LENGTH - number_length + 1)
    {
        --number_length;
        return;
    }
    else if (i < NUM_LENGTH - number_length + 1)
    {
        number_length = NUM_LENGTH - i;
    }
    return;
}

void HugeInteger::printValue()
{
 ... // здесь все ок
}

int HugeInteger::getDigit(int i) const // смотрим чему равна i-ая цифра числа
{
    if (0 <= i && i < NUM_LENGTH)
    {
        return digits[i];
    }
    else
    {
        return -1;
    }
}

int HugeInteger::getSign() const // получаем знак числа (-1 если < 0, 1 если > 0)
{
    return sign;
}

int HugeInteger::getLengthOfNumber() const //возвращаем длину числа
{
    return number_length;
}

HugeInteger HugeInteger::addHugeInteger(HugeInteger const &other)
{
    HugeInteger res; // warnind: can't find linker symbol for virtual table for HugeInteger value
    if (sign*other.getSign() > 0)
    {
        if (sign > 0)
        {
            res.setValue("+0");
        }
        else
        {
            res.setValue("-0");
        }
        int s = 0;
        for(int i = NUM_LENGTH - 1; i >= 0; --i)
        {
            s = s + digits[i] + other.getDigit(i);
            if (s > 9)
            {
                res.setDigit(i, s % 10);
            }
            s = (int) s / 10;
        }
        if (s > 0)
        {
            res.setValue("0");
        }
    }
    return res;
}




main.cpp
Код

#include <iostream>
#include ".\include\HugeInteger.h"

int main()
{
    HugeInteger d1, d2, d3;
    d1.setValue("-00999"); // d1 = -999;
    d1.printValue();
    d2.setValue("-999"); // d2 = -999;
    d2.printValue();
    d3 = d1.addHugeInteger(d2); // d3 = d1 + d2;
    d3.printValue(); // должно быть -000...001998, а печатает -000...000 
    return 0;
}



PM MAIL   Вверх
mes
Дата 8.10.2010, 11:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(FlySabaka @  8.10.2010,  10:37 Найти цитируемый пост)
Реализация верная: если вставить код функции в main.cpp выдает верный ответ. Но функция addHugiInteger работает неверно. 

для начала добавьте копи конструктор
smile


--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 11:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



Добавил
Код

HugeInteger::HugeInteger(const HugeInteger & other)
{
    sign = other.getSign();
    number_length = other.getLengthOfNumber();
    for(int i = 0; i < NUM_LENGTH; ++i)
    {
        digits[i] = other.getDigit(i);
    }
}


Пока это не принесло изменений %)
PM MAIL   Вверх
bsa
Дата 8.10.2010, 12:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 85
Всего: 196



На мой взгляд, в данной реализации класса конструктор копирования и оператор присваивания не нужны, так как нет выделения ресурсов подойдет и дефолтный.
Вот виртуальный деструктор нужно сделать обычным, так как нефиг наследовать этот класс.

FlySabaka, ты уверен, что у тебя свойство sign не может принимать нулевых значений?
PM   Вверх
FlySabaka
Дата 8.10.2010, 12:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



bsa, sign может принимать нулевое значение. я предусмотрел это на случай ошибки (например инициализация объекта класса не числом типа "+234", а фигней типа "бла-бла-бла"). Пока всех проверок на корректность я в функции не сделал.

Но при отладке addHugeInteger для указанных в main.cpp значений всё корректно: sign и other.getSign() равны -1.

Это сообщение отредактировал(а) FlySabaka - 8.10.2010, 12:37
PM MAIL   Вверх
mes
Дата 8.10.2010, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(FlySabaka @  8.10.2010,  10:37 Найти цитируемый пост)
HugeInteger& HugeInteger::operator=(const HugeInteger& rhs)
{
    if (this == &rhs) return *this; // handle self assignment
    //assignment operator
    return *this;
}


это весь код оператора присваивания ?

Добавлено через 3 минуты и 14 секунд
Цитата(bsa @  8.10.2010,  11:30 Найти цитируемый пост)
На мой взгляд, в данной реализации класса конструктор копирования и оператор присваивания не нужны, так как нет выделения ресурсов подойдет и дефолтный.

в данном случае большая вероятность добавления выделения ресурсов, так что, имхо, копи конструктор добавить сразу, чтоб глаз мозолил smile
а вот оператор присвоения для приведенного примера действительно выглядит лишним..


--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



mes, да, это весь код оператора присваивания. Code::Blocks генерит этот код при создании класса с помощью визарда (опционально).

Хотя я вроде нигде не присваиваю объекты класса HugeInteger друг другу, так что этот код не используется (насколько я понимаю).

Это сообщение отредактировал(а) FlySabaka - 8.10.2010, 12:57
PM MAIL   Вверх
mes
Дата 8.10.2010, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(FlySabaka @  8.10.2010,  11:54 Найти цитируемый пост)
Хотя я вроде нигде не присваиваю объекты класса HugeInteger друг другу, так что этот код не используется (насколько я понимаю).

ну не знаю...
Цитата(FlySabaka @  8.10.2010,  10:37 Найти цитируемый пост)
d3 = d1.addHugeInteger(d2); // d3 = d1 + d2;

 smile 


--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 12:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



mes,  понял. Согласен что сморозил глупость  smile 

Но проблема все равно возникает до присваивания, в теле функции addHugeInteger при создании объекта res класса HugeInteger, как я и писал выше. Безусловно предпосылки к этой проблеме находятся где-то в другом месте (мож конструктор у меня какой-то не такой, а?) .. 

Это сообщение отредактировал(а) FlySabaka - 8.10.2010, 13:03
PM MAIL   Вверх
mes
Дата 8.10.2010, 13:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(FlySabaka @  8.10.2010,  11:58 Найти цитируемый пост)
 понял. 

ну тогда и как исправить ошибку, как мне кажется Вы уже поняли
smile



--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



mes, Вы намекаете, что ошибка в операторе присваивания? можно уточнить, в чём именно ошибка, а то недогоняю?  smile 
PM MAIL   Вверх
mes
Дата 8.10.2010, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(FlySabaka @  8.10.2010,  11:58 Найти цитируемый пост)
Но проблема все равно возникает до присваивания,


Цитата(FlySabaka @  8.10.2010,  10:37 Найти цитируемый пост)
 Реализация верная: если вставить код функции в main.cpp выдает верный ответ

не стыкуется smile

Добавлено через 2 минуты и 52 секунды
Цитата(FlySabaka @  8.10.2010,  12:05 Найти цитируемый пост)
можно уточнить, в чём именно ошибка, а то недогоняю

раз в main выдает правильно, значит потеря идет при передаче результата
поэтому вначале я предположил , что у Вас нет копи конструктора..
оказалось проще: Вы просто добавили пустой (по смыслу работы) оператор присваивания
 smile

Добавлено через 5 минут и 10 секунд
уберите оператор присваивания, перенеся селфхандлинг в копиконструктор
(хотя можно и его убрать )



--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 13:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



mes, спасибо за помощь.
Изменил оператор присваивания на
Код

HugeInteger& HugeInteger::operator=(const HugeInteger& rhs)
{

    /*if (this == &rhs) return *this; // handle self assignment
    //assignment operator*/
    sign = rhs.getSign();
    number_length = rhs.getLengthOfNumber();
    for(int i = 0; i < NUM_LENGTH; ++i)
    {
        digits[i] = rhs.getDigit(i);
    }
    return *this;
}


Приблизительно понял, почему не работает "старая версия". Буду экспериментировать ... учиться, учиться и ещё раз учиться smile

P.S. По пути еще косяки нашёл в реализации функции, так что диву даюсь почему она мне правильно выдавала ответы непосредственно в main.cpp.

Это сообщение отредактировал(а) FlySabaka - 8.10.2010, 13:18
PM MAIL   Вверх
mes
Дата 8.10.2010, 13:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



а чего self-handling закомментили ? полезная вещь smile

а наверно из за этого :
Цитата(mes @  8.10.2010,  12:06 Найти цитируемый пост)
хотя можно и его убрать )

но тут я о копиконструкторе говорил smile

Цитата(FlySabaka @  8.10.2010,  12:16 Найти цитируемый пост)
  number_length = rhs.getLengthOfNumber();

в данном случае имхо нагляднее будет

Код

number_length = rhs. number_length;



--------------------
PM MAIL WWW   Вверх
FlySabaka
Дата 8.10.2010, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 13
Регистрация: 24.9.2010
Где: г.Новосибирск

Репутация: нет
Всего: нет



mes, здесь в операторе присваивания я его просто забыл удалить (что собственно уже сделано), в копи конструктор вставил. 

Я понимаю, что лимит глупых вопросов я на сегодня исчерпал, но тем не менее, как нам удаётся получить доступ к закрытым данным класса делая такой вот финт:

Код

number_length = rhs. number_length;

?

Так действительно намного нагляднее smile
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0884 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.