Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

конвертер

41K
24 января 2009 года
DunhiL
8 / / 24.12.2008
помогите сделать вот такое задание: есть конвертер(перевод длины из одной единицы измерения в другую) на переменной структуре + обьявления. код конвертера я написал.
но теперь его надо переписать чтобы в нем были следующие вещи:
1)конструирование значения
2)копирование обьекта
3)копирующее присваивание
немного непонятно где можно использовать эти операции.
Код:
#include <iostream>

using namespace std;

enum scaleStatus { MILE, YARD, NM, INCH, FOOT };

struct LengthScale
{
    double length;
    scaleStatus type;
    union
    {  
        double KM;
        double MILE;
        double YARD;
        double NM;   //Морские мили (узлы)
        double INCH; // Дюймы
        double FOOT;
    };
};

void toKM(LengthScale* scale)
{
    switch (scale->type)
    {
        case MILE :
        {
            scale->length = 1.61 * scale->MILE;
            break;
        }
        case YARD :
        {
            scale->length = 0.0009 * scale->YARD;
            break;
        }
        case NM :
        {
            scale->length = 1.85 * scale->NM;
            break;
        }
        case INCH :
        {
            scale->length = 0.00002 * scale->INCH;
            break;
        }
        case FOOT :
        {
            scale->length = 0.0003 * scale->FOOT;
            break;
        }
    }
}

void fromKM(LengthScale* scale)
{
switch (scale->type)
    {
        case MILE :
        {
            scale->length = 0.62 * scale->KM;
            break;
        }
        case YARD :
        {
            scale->length = 1093.61 * scale->KM;
            break;
        }
        case NM :
        {
            scale->length = 0.54 * scale->KM;
            break;
        }
        case INCH :
        {
            scale->length = 39370.08 * scale->KM;
            break;
        }
        case FOOT :
        {
            scale->length = 3280.84 * scale->KM;
            break;
        }
    }
}

int main()
{
    LengthScale l;
    l.type = MILE;
    l.MILE = 100;
    toKM(&l);
    cout << l.MILE << "[MILE] is " << l.length << "[KM]" << endl;
    l.KM = 85;
    fromKM(&l);
    cout << l.KM << "[KM] is " << l.length << "[MILE]" << endl;
    l.type = YARD;
    l.YARD = 1200;
    toKM(&l);
    cout << l.YARD << "[YARD] is " << l.length << "[KM]" << endl;
    l.KM = 22;
    fromKM(&l);
    cout << l.KM << "[KM] is " << l.length << "[YARD]" << endl;
    l.type = NM;
    l.NM = 74;
    toKM(&l);
    cout << l.NM << "[NM] is " << l.length << "[KM]" << endl;
    l.KM = 3;
    fromKM(&l);
    cout << l.KM << "[KM] is " << l.length << "[NM]" << endl;
    l.type = INCH;
    l.INCH = 250;
    toKM(&l);
    cout << l.INCH << "[INCH] is " << l.length << "[KM]" << endl;
    l.KM = 10;
    fromKM(&l);
    cout << l.KM << "[KM] is " << l.length << "[INCH]" << endl;
    l.type = FOOT;
    l.FOOT = 68;
    toKM(&l);
    cout << l.FOOT << "[FOOT] is " << l.length << "[KM]" << endl;
    l.KM = 5;
    fromKM(&l);
    cout << l.KM << "[KM] is " << l.length << "[FOOT]" << endl;
    cin.get();
    cin.get();
    return 0;
}
1.9K
24 января 2009 года
GreenRiver
451 / / 20.07.2008
Цитата: DunhiL

...


"Когда вы говорите, Иван Васильевич, ощущение такое, что вы бредите" (c)
Извините :) Но приведенный код, это просто ужас...

1. LengthScale содержит фактически два одинаковых поля численного значения величины.
2. Причем эти величины дают почву для множества ошибок. Например, функция ToKM изменит в переменной поля type и length, а union поле останется тем же, и если переменная будет дальше использоваться - получится что в ней тоже число, что и до конвертации, но единицы измерения уже Км...

Цитата: DunhiL

1)конструирование значения


Вот оно:

 
Код:
LengthScale l;
    l.type = MILE;
    l.MILE = 100;


Цитата: DunhiL

2)копирование обьекта


Что может быть проще...

 
Код:
LengthScale l,m;
    m = l;

Цитата: DunhiL

3)копирующее присваивание


Радуйтесь, присваивание в пункте 2 - копирующее.

87
25 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: DunhiL
помогите сделать вот такое задание: есть конвертер(перевод длины из одной единицы измерения в другую)


Я бы обошелся вообще без объектов. Что-то типа:

Код:
namespace LengthScale
{
    enum       scaleStatus { MILE, YARD,    NM,   INCH,     FOOT,   KM};
    const double scale[] = { 0.62, 1093.61, 0.54, 39370.08, 3280.84, 1.0};
    double Convert(double value, int from, int to)
    {
        return value * scale[to] / scale[from];
    }
};

int main()
{
    double km = 1610.0;
    double miles = LengthScale::Convert(km, LengthScale::KM, LengthScale::MILE);
    cout << miles << endl;

    return 0;
}


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

Должно быть что-то типа:

Код:
// Это абстрактный класс, у которого
//    должно быть нужное кол-во наследников
//    (по одному на каждый вид преобразования)
class Convert
{
protected:
    double initVal, convertVal;
public:
    double GetInit(){return initVal;}
    double GetConvert(){return convertVal;}
    Convert(double val){initVal = val;}

    virtual void Compute() = 0;
};

struct KM_to_MILE : public Convert
{
    KM_to_MILE(double val):Convert(val){}
    virtual void Compute()
    {
        convertVal = initVal / 1.61;
    }
};

int main()
{
    KM_to_MILE km(1610.0);

    cout << km.GetInit() << " km => ";
    km.Compute();
    cout << km.GetConvert() << " mile" << endl;

    return 0;
}
1.9K
25 января 2009 года
GreenRiver
451 / / 20.07.2008
Цитата: Kogrom

Должно быть что-то типа:
...


Парень окончательно запутается :(
В задании вроде ничего не говорится про наследование, нужно просто написать класс и перегрузить в нем оператор присваивания.

Дело в том, что пример который дал преподаватель мягко говоря странный...

87
25 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: GreenRiver
Парень окончательно запутается :(
В задании вроде ничего не говорится про наследование...


Где задание-то? Четкого задания вроде бы и не было.

Чтоб не путаться - я привел простейший пример без классов (можно было бы и без пространства имен для простоты, но я не люблю "свободные" енумы). Недостаток того примера в том, что компилятор не знает из какого типа величины в какой переводить. Т. е. он спокойно переварит следующее:

double yard = LengthScale::Convert(miles, LengthScale::KM, LengthScale::MILE);

но смысл уже будет неверный. Для того, чтобы это устранить и нужны классы. При этом можно либо использовать иерархию классов, а в функции давать указатель на абстрактный класс-предок, либо использовать некрасивые манипуляции, типа определения типа объекта по какому-то его данному.

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

87
25 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: Kogrom
но смысл уже будет неверный. Для того, чтобы это устранить и нужны классы. При этом можно либо использовать иерархию классов, а в функции давать указатель на абстрактный класс-предок...


Короче что-то типа того:

Код:
class LengthType
{
    double val;
public:
    virtual double GetScale() = 0;
    virtual double GetValue(){return val;}
    virtual void SetValue(double v){val = v;}
    virtual void Convert(LengthType *p)
    {
        double res = p->GetValue() * this->GetScale() / p->GetScale();
        this->SetValue(res);
    }
    LengthType(double v):val(v){}
};


class KM : public LengthType
{
    static const double scale = 1.0;
public:
    virtual double GetScale(){return scale;}
    KM(double v):LengthType(v){}
};


class Mile : public LengthType
{
    static const double scale = 0.62;
public:
    virtual double GetScale(){return scale;}
    Mile(double v):LengthType(v){}
};


int main()
{
    KM km = 161.11;
    Mile mile = 0.0;

    mile.Convert(&km);
    cout << mile.GetValue() << " miles" << endl;

    km.SetValue(0.0);
    km.Convert(&mile);
    //km.Convert(&km); // теперь нет ошибки, хотя еще нет смысла
    cout << km.GetValue() << " km" << endl;

    return 0;
}
1.9K
27 января 2009 года
GreenRiver
451 / / 20.07.2008
Посты из "Для новичков" переехали в студенты - я даже не заметил... Автор видимо тоже :)
Переехали кстати не все посты, вот начало.

Задача проще решается структуркой double + enum (код тута)... В вашем варианте легко запутаться, особенно учитывая, что при конвертации нужны отдельные указатели для каждой СИ. На мой взгляд использовать наследование здесь необоснованно.
87
27 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: GreenRiver
Задача проще решается структуркой double + enum (код тута)...


Нет. Проще использовать enum + массив соответствующих коэффициентов. Тогда никакой switch - case не нужен. Будет короче, и внести новую СИ проще.

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

Суть вот в чем: величина в исходной СИ переводится в километры, затем километры переводятся в величину трубуемой на выходе СИ (вместо километров можно использовать другуюпромежуточную СИ).

Цитата: GreenRiver
В вашем варианте легко запутаться, особенно учитывая, что при конвертации нужны отдельные указатели для каждой СИ. На мой взгляд использовать наследование здесь необоснованно.


В последнем моем примере запутаться трудно - он довольно короткий, и сравнительно легко читаемый. Плюс тут как раз в том, что пользователь получает результат, соответствующий типу переменной. Еще плюс в том, что не нужно знать никаких констант, енумов для использования преобразования. И при чем тут указатели? Для каждой СИ у меня нужен отдельный класс-наследник, а не указатель.

1.9K
28 января 2009 года
GreenRiver
451 / / 20.07.2008
Цитата: Kogrom

... И при чем тут указатели? Для каждой СИ у меня нужен отдельный класс-наследник, а не указатель.



При том, что есть у нас например величина в 25 километров... Объявлена вот так: KM km = 25;
Во первых, чтобы перевести в мили нужно завести ещё одну переменную класса Mile ... или указатель на Mile.
Во-вторых, функция Convert базового класса изменит значение val (использование промежуточной СИ - километров, очень хорошее решение, я не подумал про это) ... но вот сама переменная останется того, же класса KM... От того, что сработал метод базового класса тип переменной не изменится. Получается мы играем на том, что компилятор будет обращаться с этой переменной, как с переменной другого типа... Я думаю это сработает за счет виртуальных функций и статических полей, но все это представляется мне ненадежным...
Я не критикую, сам пытаюсь разобраться :)

87
28 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: GreenRiver
При том, что есть у нас например величина в 25 километров... Объявлена вот так: KM km = 25;
Во первых, чтобы перевести в мили нужно завести ещё одну переменную класса Mile ... или указатель на Mile.


Величина km хранит длину только в километрах. Она не дожна хранить ее в милях. Т.е. пользователь всегда будет уверен, что в данной переменной используется определенная СИ.

Соответственно, чтобы перевести ее в мили, нам требуется переменная, которая хранит длину в милях. При этом значение (val) самой переменной km при конвертации не меняется. Меняется только значение переменной типа MILE.

В функции Convert значение исходной переменной передается по указателю. Это обычный прием - ссылаться на переменную базового типа, чтобы пользователь мог подставить указатель на любой класс-потомок. В общем, как я понимаю, это пример полиморфизма: Convert использует виртуальный метод GetScale(), который для каждого потомка возвращает разный коэффициент.

Цитата: GreenRiver
Во-вторых, функция Convert базового класса изменит значение val (использование промежуточной СИ - километров, очень хорошее решение, я не подумал про это) ... но вот сама переменная останется того, же класса KM...


Изменяется не величина из которой переводят, а в которую переводят. То есть, если я пишу

KM km = 161.11;
mile.Convert(&km);

то km останется преждним, в mile запишется значение 100 (100 милей равно 161.11 км - вроде логично).

В любом случае, в этом подходе есть и плюсы и минусы. Но я привел 2 примера - в стиле C и в стиле C++. Выбор есть.

1.9K
28 января 2009 года
GreenRiver
451 / / 20.07.2008
Угу, я понял идею. Единственное, что меня по прежнему смущает так то, что для конвертации из одной СИ в другую нужно две переменные.. Но Вы правы есть и плюсы и минусы...

P.S. похоже нам эта тема интереснее, чем топик-стартеру :)
87
28 января 2009 года
Kogrom
2.7K / / 02.02.2008
Цитата: GreenRiver
P.S. похоже нам эта тема интереснее, чем топик-стартеру :)


Я сюда хожу не для того, чтобы студентам во время сессии помогать, а чтобы самому учиться и с умными людьми поговорить. Поэтому для меня не важно, кто создал тему - важна сама тема.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог