It WORKS!!

guys i know it may not seem like much to you that this little program works but i'm fairly proud that i achieved my goal c: i shall share it with you all.

I do not know much about templates or class inheritance or more advanced features of c++ but to my best of knowledge this is the neatest way i could code this.

if you have any topics i could study in particular to have saved time/been more efficient in this programs creation please share.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
  #include <iostream>
#include <string>
using namespace std;
/*****************************************************
*Point of program: enter the width or height of
*the listed rectangles to calculate and keep track
*of the area
*
*There will be 5 rectangles in the list
******************************************************/

//CLASS for paramaters of all rectangles.
class rectangle{
private:
    int width = 0;
    int height = 0;
public:
    void setheight(){
    cin >> height;
    }
    void setwidth(){
    cin >> width;
    }
    void displaywidth(){
    cout << width << endl;
    }
    void displayheight(){
    cout << height << endl;;
    }
    void displayarea(){
    cout << height * width << endl << endl;
    }


};
int main()
{
    //we will be controlling 5 rectangles
rectangle one, two, three, four ,five;


bool running = true;
int input;
int b;
int type;

while (running == true){
        /******************
        *Create the table
        *******************/
 cout << "Rectangle 1:";
 cout << "Height:";
 one.displayheight();
 cout << "Width:";
 one.displaywidth();
 cout << "Area:";
 one.displayarea();

  cout << "Rectangle 2:";
 cout << "Height:";
 two.displayheight();
 cout << "Width:";
 two.displaywidth();
 cout << "Area:";
 two.displayarea();

  cout << "Rectangle 3:";
 cout << "Height:";
 three.displayheight();
 cout << "Width:";
 three.displaywidth();
 cout << "Area:";
 three.displayarea();

cout << "Rectangle 4:";
 cout << "Height:";
 four.displayheight();
 cout << "Width:";
 four.displaywidth();
 cout << "Area:";
 four.displayarea();

  cout << "Rectangle 5:";
 cout << "Height:";
 five.displayheight();
 cout << "Width:";
 five.displaywidth();
 cout << "Area:";
 five.displayarea();

/*************
*Get user input asking which rectangle to modify and then ask for values
**************/

 cout << "which rectangle do you want to modify?:";

 cin >> input;

 if (input == 1){
    cout << "height = 1" << endl << "width = 2" << endl;
    cout << "type 1 or 2:";
    cin >> type;
    if(type == 1){

    cout << "set height:";
        one.setheight();
    }
    else if (type == 2){

    cout << "set width:";
        one.setwidth();
    }
 }
  else if (input == 2){
    cout << endl << "height = 1" << endl << "width = 2" << endl;
    cout << "type 1 or 2:";
    cin >> type;
    if(type == 1){

    cout << "set height:";
        two.setheight();
    }
    else if (type == 2){

    cout << "set width:";
        two.setwidth();

    }
 }
 else if (input == 3){
    cout << endl << "height = 1" << endl << "width = 2" << endl;
    cout << "type 1 or 2:";
    cin >> type;
    if(type == 1){

    cout << "set height:";
        three.setheight();
    }
    else if (type == 2){

    cout << "set width:";
        three.setwidth();
    }
 }
  else if (input == 4){
    cout << endl << "height = 1" << endl << "width = 2" << endl;
    cout << "type 1 or 2:";
    cin >> type;
    if(type == 1){

    cout << "set height:";
        four.setheight();
    }
    else if (type == 2){

    cout << "set width:";
        four.setwidth();
    }
 }
 else if (input == 5){
    cout << endl << "height = 1" << endl << "width = 2" << endl;
    cout << "type 1 or 2:";
    cin >> type;
    if(type == 1){

    cout << "set height:";
        five.setheight();
    }
    else if (type == 2){

    cout << "set width:";
        five.setwidth();
    }
 }
 //clear the screen
cout << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl;


}


    return 0;
}


was not sure where to post.
The first thing I noticed is you mixed your your logic with your trivial objects, by this I mean instead of passing a value the set functions, you're asking for use input like a procedure.
Congrats man!

I am a beginner in C++ myself and I feel extremely happy when I get something to work.
And it really frustrating if I don't haha.

However, even though I am probably on the same level as you I can recommend a few things:

1.If you would like to set the private variables of a class, you can do so through class constructors, that way you will save your time and not have to call multiple class member functions to set the values for your private variables. Class constructors go under public: and they have the same name as your class so your code would look like this -

1
2
3
4
5
6
7
8
9
10
class rectangle
{
    public:
        retangle(int width, int height);
        // your get() methods
        //now you can get rid of setWidth(), and setHeight()
    private:
       //your variables
};

I just noticed that you are not using your set() methods to create an object but just to modify it so disregard this, unless you didn't know about it.

2. Shorter, more concise code. It is generally a good idea to use repeatable code such as functions, when you are outputting the table of rectangles.

For example, why not do this?

1
2
3
4
5
6
7
8
9
10
11
12
class rectangle
{
    private: 
         //your stuff
    public:
         void show()
          {
            std::cout << "Height: " << height
                      << "\nWidth: " << width
                      << "\nArea: " << (height * width) << std::endl;
           }
};

That way in your main you could do:
1
2
3
4
std::cout << "Rectangle 1: " << std::endl;
one.show();

// you just saved 5 lines of code! 


The same would apply for your other functions, short more concise code = easier on the eyes = higher maintainability. I know we are noobs but we should pick up these good habits in order to become better at programming.
Last edited on
You could use an array of 5 rectangles so you don't have to repeat the code for each rectangle you want to handle.
1
2
3
4
5
6
7
8
9
10
for (int i = 0; numberOfRectangles; ++i)
{
	cout << "Rectangle " << i << ":";
	cout << "Height:";
	rectangles[i].displayheight();
	cout << "Width:";
	rectangles[i].displaywidth();
	cout << "Area:";
	rectangles[i].displayarea();
}
Last edited on
@Peter87 that is brilliant, or use a vector!
For what @Peter87 said:

I think you can do something like this:


1
2
3
4
5
6
7
8
9
10
11
12
13

int main()
{
rectangle rects[5]; //this initializes 5 objects of rectangle class to 0 width and height
for(int i = 0; i < 5 ; i++)
    {
     std::cout << "Rectangle " << i << std::endl;
     rects[i].show();  
     }

}



Edit:
that code would output Rectangle 0, to change that simply add one to output
 
std::cout << "Rectangle " << i + 1 << std::endl;

Last edited on
I took your guys's advice and ended up with this :D

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include <iostream>
#include <string>
using namespace std;
/*****************************************************
*Point of program: enter the width or height of
*the listed rectangles to calculate and keep track
*of the area
*
*There will be 5 rectangles in the list
******************************************************/

//CLASS for paramaters of all rectangles.
class rectangle{
private:
    int width = 0;
    int height = 0;
public:
    void setheight(){
    cin >> height;
    }
    void setwidth(){
    cin >> width;
    }
    void displaywidth(){
    cout << width << endl;
    }
    void displayheight(){
    cout << height << endl;;
    }
    void displayarea(){
    cout << height * width << endl << endl;
    }



};
int main()
{
    //we will be controlling 5 rectangles
rectangle rect[5];


bool running = true;
int type;

while (running == true){
        /******************
        *Create the table
        *******************/
int i = 1;
for (i; i<=4; i++){

    cout << "Rectangle:" << i;
    cout << endl;
    cout << "Height:";
     rect[i].displayheight();
    cout << "Width:";
     rect[i].displaywidth();
    cout << "Area:";
     rect[i].displayarea();


}



/*************
*Get user input asking which rectangle to modify and then ask for values
**************/

 cout << "which rectangle do you want to modify?:";
 cin >> i;
 cout << "what do you want to modify? (type 3 to exit)";
 cout << endl;
 cout << "1 = height" << endl;
 cout << "2 = width" << endl;
 cout << "Enter option 1 or 2:";
 cin >> type;
 if (type == 1){
        cout << "set Height:";
    rect[i].setheight();
 }
 else if (type == 2){
    cout << "set width";
    rect[i].setwidth();
 }
 else if(type == 3){
    return 0;
 }
 //clear the screen
cout << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl;


}



}

i changed it to 4 in the loop because of spacing issues. also was able to cut the code down by 100 lines.
Last edited on
Nice!
I can think of a few more improvements:

Change:

1
2
3
4
private:
    int width = 0;
    int height = 0;
public:


To

1
2
3
4
5
private:
    int width;
    int height;
public:
    rectangle(int w, int h): width(w), height(h) {}



The other thing I could note, which will help you a lot when displaying class information, is ostream overloading. Consider this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <string>

// Your standard class, defining an object.

class Obj
{
private:
    std::string output;
public:
    Obj(std::string o): output(o) {}
    std::string GetOutput() { return output; }
    ~Obj() {}
};

// Overloading the ostream operator<<, how to handle printing a class
// Imagine pushing a bunch of information to cout, then returning it
// for printing

std::ostream& operator<< (std::ostream& os, Obj& o)
{
    os << o.GetOutput() << "\n";
    return os;
}

// Your usual main function

int main()
{
    Obj MyObj("This is an Object"); // Init a class
    std::cout << MyObj; // Print class out using cout
    return 0;
}


EDIT 1:

Another thing I spotted was this:

1
2
int i = 1;
for (i; i<=4; i++){


You declared 5 rectangles, you will only be storing information for 4 ( 1-4 rather than 0-4)

Try: for(int i = 0; i < 5; i++)


EDIT 2:

Previous edit lead me on to this. You have what we call a "magic" number. You declare the number 5 as a literal. You should avoid this as if you want to change the number, you have to change the number through all the code, instead do something such as:

#define RectCount 5 then use it like any variable: for(int i = 0; i < RectCount; i++)


EDIT 3:

This code here:

 
cout << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl << endl;


could be improved via a function:

 
void ClearScr() { for(int i = 0; i < 512; i++) std::cout << "\n"; // I think 512 lines is the usual terminal back log limit 


Another thing is: using namespace std;

The question of use is debatable depending of circumstances. I know you are a beginner, but there is nothing saying you can't learn without it. The problem with this is if you use another library of functions, as your programming progresses, there may be conflicting values within the libraries. To correctly choose the right one, you would access through scope std::cout or std::string.
Last edited on
Quick question megatron 0 , would using #define RectCount 5 be the same as creating a:

 
const RectCount = 5;
I'm not even sure is const identifier is legal C++. Just checked, it's not according to G++:

error: ‘identifier’ does not name a type const identifier = 5;

The #define keyword does exactly that, it defines an identifier with a value:

1
2
3
4
5
6
7
#define ANumber 5
#define IsPassable 1

int Array[ANumber]; // Same as int Array[5];

if(IsPassable) // Same as if(1)


EDIT:

You can do some funny/bizarre things with define:

1
2
3
4
5
6
7
#define IAMACAT int main()
#define IHATEDOGS return 0;

IAMACAT
{
    IHATEDOGS
}
Last edited on
DO NOT USE #define TO DECLARE CONSTANTS

In fact... #define should largely be avoided for several reasons... which I am too tired to get into now.

Declaring const identifiers is hands-down the better way to go:

1
2
3
#define ANumber 5  // <- BAD NEVER DO THIS

const int ANumber = 5;  // <- much better way of doing the exact same thing. 
Disch is right, I never use it but was a better option for you rather than writing literals.

EDIT:

const int ANumber = 5; // <- much better way of doing the exact same thing.


I have to debate about this. It's technical not the same thing. Define would replace all identifiers with the value at compile time. Where as defining a const int will take 4 bytes constantly in the program?
Last edited on
It's technical not the same thing.


Conceptually, it's the same thing.

Implementation-wise, it's almost always the same thing.

The only thing that's really different about it is it follows C++ language, identifier, and scope rules which macros have a very bad habit of ignoring/sidestepping/destroying.

Where as defining a const int will take 4 bytes constantly in the program?


Optimizers are smart enough to replace the constant with its value when necessary. That's the whole reason the 'const' keyword is in the language in the first place. In virtually all practical examples... optimized code will be compiled to the exact same thing regardless of whether you used a macro or a constant.


Besides... if you are worrying about 4 bytes of memory you have your priorities screwed up.


EDIT:

Also... using 4 additional bytes doesn't mean anything anyway. Memory is not allocated to your program on a per-byte basis. It's allocated in much larger pages (several kilobytes).

So using a few extra bytes does not mean your program will use more memory unless that 4 bytes happens to push you into the next page, which is unlikely.



Though you are right.... using #defines is definitely better than putting magic numbers all over your code. I still would not recommend it.
Last edited on
You are probably right about all that. I just wanted to say something in case I had my information mixed up, and not saying anything I might have kept following the same information which would of stuck it in deeper.

I usually worry about every byte, I'm hoping to be writing firmware for devices which can have very little RAM, so every byte counts I guess. I know 4 bytes mean nothing in this level of application programming, again I just wanted to check my sources.


Memory is not allocated to your program on a per-byte basis. It's allocated in much larger pages (several kilobytes).


Are you sure about that? Or are you speaking purely for C++? When I have written code for the 386 the assembler compiles my code almost exactly as predicted by the length of an instruction. Compiling with C is slightly bigger on average, perhaps the higher level language has to accommodate abstraction for space. I'm not sure about the exact syntax to processor instruction details, might give me the opportunity for some late night reading. Also this is with no standard library and writing everything on your own two feet ( Boot sectors, OS implementation and the like, I'm sure you know how it goes).

Though you are right.... using #defines is definitely better than putting magic numbers all over your code. I still would not recommend it.


Me neither to be frank, I thought it would of been easier to implement for his example, I figured he was writing this to test out his code rather than creating a substantial code base for it. I figured a single define wasn't too bad to complain about rather than having to go into details.

Cheers for the information anyway buddy, I love to learn off those who came before.
> It's technical not the same thing.
>> Conceptually, it's the same thing.

Conceptually, the two are completely different. One is a token replacement mechanism for source code, the other injects a strongly typed constant expression into the current scope.

For instance:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//////////////////////////  a header file //////////////////////
// which may be included after having first included <cassert>

#ifdef NDEBUG
    #define NDEBUG_WAS_DEFINED
    #undef NDEBUG
#endif // NDEBUG
#include <cassert> // *** not idempotent

inline void foo( int ) // code under integration test
{
    // assert

    // ...
}

#ifdef NDEBUG_WAS_DEFINED
    #define NDEBUG
    #include <cassert> // *** not idempotent
    #undef NDEBUG_WAS_DEFINED
#endif // NDEBUG_WAS_DEFINED

inline void bar( int ) // production code from earlier version
{
    // assert

    // ...
}
Conceptually, the two are completely different. One is a token replacement mechanism for source code, the other injects a strongly typed constant expression into the current scope.


This is what I thought but I'm not one to argue. There's always a good chance I am wrong due to professional inexperience.
Nevertheless, the basic point that Dish was making is a very valid one: when there is a choice, favour a compile-time mechanism over a preprocessor mechanism.

constexpr std::size_t N = 100 ; over #define N 100

template< typename FPT > constexpr FPT multiplier = 3.56; // C++14 over #define MULTIPLIER 3.56
I meant conceptually from a high level:

1
2
#define VAL 3.14
const double val = 3.14


VAL and val are both constants. They're both an alias used to represent some other fixed value with a recognizable name, rather than typing that value into the source directly.

They accomplish that same task and fulfill that same role. So conceptually, they are the same.

Implementation-wise, yes... they are different. But not by much.
Topic archived. No new replies allowed.