-1
#include <iostream>
#include <fstream>
using namespace std;

class Shape
{
  public:
    string name;
    double width, height, radius;
  public:
    void set_data (double a, double b)
    {
        width = a;
        height = b;
    }
    virtual double area() = 0;
};

class Rectangle: public Shape
{
public:
    double area ()
    {
        return (width * height);
    }
};

class Triangle: public Shape
{
public:
    double area ()
    {
        return (width * height)/2;
    }
};

class Circle : public Shape
{
  public:
    double area ()
    {
        return 3.1415 * (radius * radius);
    }
};

int main()
{
    int N;
    cin >> N;

    Rectangle Rect;
    Triangle Tri;
    Circle Circ;
    string* S = new string[N];

    if(N == 1) {
      cin >> Rect.name >> Rect.height >> Rect.width;
      cout << Rect.area();

      return 0;
    } 
    else
{
    for(int i = 0; i < N; i++)
    {
        cin >> S[i];

        if(S[i] == "Rectangle")
        {
            cin >> Rect.height;
            cin >> Rect.width;
        }
         else if(S[i] == "Triangle")
             {
                 cin >> Tri.height;
                 cin >> Tri.width;
             }
             else if(S[i] == "Circle")
                  {
                      cin >> Circ.radius;
                  } 

    }
}
    cout << Rect.area() << " " << Tri.area() << " " << Circ.area();

  delete [] S;

    return 0;
}

the code works well in the Test 1 and Test 2, but in Test 3 give an error... im need to input N number(count of Shapes) and display in Output all areas in ascending order...

For Example:

====== TEST #1 =======

Input:

1

Rectangle 4 3

Output: 12

The True Answer: 12

OK!

====== TEST #2 =======

Input:

3

Triangle 4 6

Rectangle 2 3

Circle 3

Output: 6 12 28.2735

The True Answer: 6 12 28.2735

OK!

====== TEST #3 =======

Input:

5

Triangle 4 6

Rectangle 2 3

Circle 4

Triangle 7 11

Triangle 3 5

Output: 6 7.5 50.264

The True Answer: 6 7.5 12 38.5 50.264

Error!

Please tell me, why my code is not working?

Var_the_an
  • 1
  • 1
  • 3
  • Okay? Do you know how to make the program sort things? – user253751 Jul 24 '20 at 14:07
  • [Why is “using namespace std;” considered bad practice?](https://stackoverflow.com/q/1452721/430766) – bitmask Jul 24 '20 at 14:10
  • Store pointers or references in the container (e.g. `std::vector`), and use `std::sort` with appropriate lambda (e.g. `[](Shape& a, Shape& b) { return a.area() < b.area(); }`)? BTW, better signature: `virtual double area() const = 0;`. And don't forget about `override` keyword. – pptaszni Jul 24 '20 at 14:11
  • I don’t know how to solve the problem – Var_the_an Jul 24 '20 at 14:12
  • 4
    Also, from a design perspective, an abstract shape should not have a width, height or radius. These concepts do not apply on this level. Your rectangle doesn't have a radius, your circle doesn't have width and height (per se). – bitmask Jul 24 '20 at 14:13
  • You will need to dispatch on the first word of the line and create the necessary subclass of `Shape`, which will in turn read the necessary parameters from `cin` – Botje Jul 24 '20 at 14:41
  • can you write the code example? I don’t know how to change my code – Var_the_an Jul 24 '20 at 14:47
  • @Var_the_an: stackoverflow is not the place to have your exercice done. It is a place where you ask programming questions. In your post, the question is to broad and almost "how to solve my exercice". You must show that you tried something and ask why what you have done is not working. Consider editing your post according to this comment. – Heyji Jul 24 '20 at 16:46

1 Answers1

0

Basically, the comments pointed the main issues, but I want to show a specific design for the abstraction:

Let's start with a concept for a shape property classes:

class shape_property {};

template <typename T>
concept ShapeProperty = std::is_base_of_v<shape_property, T>;

For the shape class (which accepts shape properties as template parameters):

template <ShapeProperty ...Properties>
class shape : virtual public Properties... {
public:
    explicit shape(std::string name) : name(std::move(name)) {}
    virtual ~shape() = default;

    [[nodiscard]] std::string get_name() const { return name; }

    virtual void input_data() = 0;
    [[nodiscard]] virtual double area() const = 0;

protected:
    std::string name;
};

Properties examples:

class width_shape_property : shape_property {
public:
    [[nodiscard]] double get_width() const { return width; }
    void set_width(double width) { this->width = width; }

protected:
    double width;
};

class height_shape_property : shape_property {
public:
    [[nodiscard]] double get_height() const { return height; }
    void set_height(double height) { this->height = height; }

protected:
    double height;
};

class radios_shape_property : shape_property {
public:
    [[nodiscard]] double get_radios() const { return radios; }
    void set_radios(double radios) { this->radios = radios; }

protected:
    double radios;
};

Shape examples:

class rectangle : public shape<width_shape_property, height_shape_property> {
public:
    rectangle() : shape("Rectangle") {}

    void input_data() override {
        double width, height;
        std::cout << "Enter width & height:" << std::endl;
        std::cin >> width >> height;
        set_width(width);
        set_height(height);
    }

    [[nodiscard]] double area() const override {
        return width * height;
    }
};

class triangle : public shape<width_shape_property, height_shape_property> {
public:
    triangle() : shape("Triangle") {}

    void input_data() override {
        double width, height;
        std::cout << "Enter width & height:" << std::endl;
        std::cin >> width >> height;
        set_width(width);
        set_height(height);
    }

    [[nodiscard]] double area() const override {
        return (width * height) / 2;
    }
};

class circle : public shape<radios_shape_property> {
public:
    circle() : shape("Circle") {}

    void input_data() override {
        double radios;
        std::cout << "Enter radios:" << std::endl;
        std::cin >> radios;
        set_radios(radios);
    }

    [[nodiscard]] double area() const override {
        return M_PI * radios * radios;
    }
};

Now, to contain the shapes in a single container, I used @MarkGarcia solution, which based on @SeanParent talk "Inheritance Is The Base Class Of Evil" with some minor modifications:

class virtual_base {
public:
    template<typename T>
    virtual_base(T &obj) : m_obj(std::make_shared<impl<T>>(obj)) {}

    void input_data() {
        m_obj->input_data();
    }

    [[nodiscard]] double area() const {
        return m_obj->area();
    }

private:
    class interface {
    public:
        virtual ~interface() = default;
        virtual void input_data() = 0;
        [[nodiscard]] virtual double area() const = 0;
    };

    template<typename T>
    class impl : public interface {
        T& m_impl_obj;

    public:
        explicit impl(T& impl_obj) : m_impl_obj(impl_obj) {}

        void input_data() override {
            m_impl_obj.input_data();
        }

        [[nodiscard]] double area() const override {
            return m_impl_obj.area();
        }
    };

    std::shared_ptr<interface> m_obj;
};

And the result:

int main() {
    std::vector<virtual_base> shapes;

    rectangle r;
    triangle t;
    circle c;

    shapes.emplace_back(r);
    shapes.emplace_back(t);
    shapes.emplace_back(c);

    for (auto &shape : shapes) {
        shape.input_data();
        std::cout << shape.area() << std::endl;
    }

    r.set_width(10);
    std::cout << shapes[0].area() << std::endl;

    return EXIT_SUCCESS;
}

Required headers:

#include <iostream>
#include <vector>
#include <memory>
#include <math.h>

For the github repository of the updated code.

Coral Kashri
  • 3,436
  • 2
  • 10
  • 22