Подтвердить что ты не робот

C/С++: периметр и площадь прямоугольников. Объем кубоидов

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

    rect a;
    a = ( -----
          !   !
          -----a );
std::cout << a.area() << std::endl;
std::cout << a.perimeter() << std::endl;

С этой целью я создал следующий класс:

class rect
{
public:
    rect():w(0), h(2) {}
    rect& operator - () { w += 0.5f; return *this; }
    rect& operator - (rect&) { w += 0.5f; return *this; }
    rect& operator -- (int a) { w += a; return *this; }
    rect& operator -- () { w += 1; return *this; }
    rect& operator ! () { h += 0.5f; return *this; }
    void clear() { w = 0; h = 2; }
    int area() { return w * h; }
    int perimeter() { return 2 * w + 2 * h; }
    int width() { return w; }
    int height() { return h; }
private:
    float w;
    float h;
};

Вот несколько примеров использования:

#include <iostream>

int main()
{
    rect a;

    a = ( -----
          !   !
          -----a );

    std::cout << a.area() << std::endl;
    std::cout << a.perimeter() << std::endl;
    std::cout << a.width()  << std::endl;
    std::cout << a.height() << std::endl;

    std::cout << std::endl;

    a.clear();

    a = ( ----------
          !        !
          !        !
          !        !
          !        !
          ---------a );

    std::cout << a.area() << std::endl;
    std::cout << a.perimeter() << std::endl;
    std::cout << a.width()  << std::endl;
    std::cout << a.height() << std::endl;

    return 0;
}

Вот мои вопросы:

  • Можно ли это сделать без привлечения арифметики с плавающей запятой? (действительно, это целая сетка)
  • Можно ли его обобщить в трехмерном случае? I.e:

    cuboid b;
    b = (  ---------
          /        /!
         ! -------! !
         !        ! !
         !        ! !
         !        !/
         ---------b );
    
    std::cout << b.volume() << std::endl;
    
4b9b3361

Ответ 1

Мне пришлось изменить оператор '/' как '+', так как не существует префикса '/' оператора. + отлично работает. О, и он использует ints. Я только проверил его один раз с предоставленным вами случаем, но насколько я мог сказать, он должен работать.

class cuboid
{
        int w,h,l;
public:
        cuboid () : w(2), h(3), l(6) {}
        cuboid& operator - () { w += 1; return *this; }
        cuboid& operator - (cuboid&) { w += 1; return *this; }
        cuboid& operator -- (int) { w += 2; return *this; }
        cuboid& operator -- () { w += 2; return *this; }
        cuboid& operator ! () { h += 1; return *this; }
        cuboid& operator + () { l += 1; return *this; }
        cuboid& operator + (cuboid&) { l += 1; return *this; }
        cuboid& operator ++ () { l += 2; return *this; }
        cuboid& operator ++ (int) { l += 2; return *this; }

        void clear () { w = 2; h = 3; l = 6; }
        int width () const { return w / 3; }
        int height () const { return h / 3; }
        int length () const { return l / 3; }
        int volume () const { return width() * height () * length (); }
        int surface_area() const { return width() * height () * 2 +
                                          width() * length () * 2 +
                                          length() * height () * 2; }
};

Смотрите в действии. http://ideone.com/vDqEm

Изменить: вам не нужны операторы ++, так как не должно быть двух + рядом друг с другом. Woops.

Ответ 2

Сорт. Легко проверить массив как прямоугольник и рассчитать материал об этом без математики с плавающей запятой, если вы предполагаете, что любой набор символов имеет равную высоту и ширину или что ваши юниты являются просто символами, а не пикселями. Таким образом, фактическая форма прямоугольника будет меняться на основе набора символов, но логически она будет по-прежнему иметь 3 символа на 2 символа.

НО, вы столкнетесь с некоторыми проблемами с 3D-корпусом. Во-первых, вы не можете представить его с использованием макета на основе сетки с использованием массива. Посмотрите на свое искусство ascii. Каков угол передней поверхности? Это не ноль, потому что вы можете наблюдать за боковым краем. Если это угол 90 градусов, если вы видите сторону, то передняя сторона также должна быть под углом. Таким образом, ваш метод представления просто не соответствует задаче представления трехмерных кубоидов.

Есть альтернатива. 3D-искусство ascii может быть абстракцией 3D-цели, о которой вы говорите. Символы слэш/обратная косая черта теперь ровно одна единица длины, то же, что и символ "-" и "!". персонажи. С учетом этого, 3D-версия также довольно тривиальна, хотя при ее отображении она будет выглядеть довольно странно.

Я имею в виду, давай, посмотри на эти кубики, они НЕ дружелюбны к евклидову:

  ---
 / /!
--- !
! !/
---

   ----
  /  /|
 /  / |
----  |
|  | /
|  |/
----

Так или иначе, предполагая, что эти вещи являются строками ascii-art, представляющими 2D или 3D фигуры, здесь вы идете:

//Skipping the validation step, assuming well formed ascii rectangles.
int height2D(char* rect, int size)
{
    int ret=0;
    int i=0;
    while(i++ < size) 
        if(rect[i] == '\n')
            ret++;
    return ret;
}

int width2D(char* rect, int size)
{
    int ret=0;
    while(rect[ret] == '-' && ret < size)
        ret++;
    return ret;
}

int area2D(char* rect, int size)
{
    //return height2D(rect, size) * width2D(rect, size);
    //ppfffft!
    return size;
}

int perimiter2D(char* rect, int size)
{
    return 2 * height2D(rect, size) + 2 * width2D(rect, size);
}



//Skipping the validation step, assuming well formed ascii cuboids
int height3D(char* rect, int size)
{
    int ret=0;
    int i=0;
    int depth;

    while(i++ < size) 
        if(rect[i] == '\n')
            ret++;
    depth = depth3D(rect, size);
    return ret - depth + 2;
}

int width3D(char* rect, int size)
{
    int ret=0;
    int i=0;
    while(rect[i] != '-' && ret < size)
        i++;
    while(rect[i++] == '-' && ret < size)
        ret++;

    return ret;
}

int depth3D(char* rect, int size)
{
    int ret=0;
    while(rect[ret] == ' ' && ret < size)
        ret++;
    return ret+1;
}

int volume3D(char* rect, int size)
{
    return height3D(rect, size) * width3D(rect, size) * depth3D(rect, size);
}

int area3D(char* rect, int size)
{
    return 2 * heigh3D(rect, size) * width3D(rect, size) + 
           2 * heigh3D(rect, sise) * depth3D(rect, size) + 
           2 * width3D(rect, size) * depth3D(rect, size);
}

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