How to use ONE variable for saving TWO results of calculations

Good morning everybody,

as I am new to the forum and this is my first post, I would like to introduce myself beforehand. I am an IT specialist trainee in application development in my first year (started in mid September). The programming language we are learning is C++.

My level of experience in programming is very limited, which is why I kindly ask for your support.
The only thing I know how to do is how to initialize variables, type in values and print them out on the screen. I also know how to use loops but what I need in the following example probably requires one or two functions with parameters (at least that would be my guess).

What I would like the program to do for me is to calculate ALL possible lengths and surfaces of a hipped roof (sides one and three = trapeze, sides two and four = triangle if you look down at it from the sky).

The problem I am facing is that I want it to calculate

1 the surfaces and lengths WITH ROOF OVERHANG
2 the surfaces and lengths WITHOUT ROOF OVERHANG

but I absolutely do not want to use 2 different variables for each value/(intermediate) result.
Instead, please have each (intermediate) result saved in one variable.
I think the way to do this is by using the variable private so I can use it with the same name for different calculations and that is why I believe functions may be required for that...how do you do that?

For instance, I have got 2 different lengths when it comes to ridge heights/baselines/angle rafters/middle rafters but I want to use the same variable(name) for that calculation (maybe in 2 functions, one called "calcWoutRoofOverhang"(){}, 2nd "calcWithRoofOverhang(){}. How do I do that the easiest way?

What the program does:

1) User types in length, width, 4 roof pitches(slopes?) and 4 roof overhangs of the house
2) Depending on the values you type in, the program calculates various lengths and roof surfaces (around 200 when the program is finished) and saves the results in the corresponding variables
3) The output shows us the results of the calculated values

If you scroll down until you see "VERARBEITUNG", you will find the formulas/calculations for results WITHOUT ROOF OVERHANG ("OHNE DACHÜBERSTAND").
In the end, "WITH ROOF OVERHANG" is pretty similar, you only need to add one length or angle more to get the result.
A concrete example: The variable hFirst (=HeightRidge)needs to be named the same for both calculations with roof overhang and without it.
I do not want to rename it to hFirst2 or something.

Here is the code:

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
  #include <math.h>
#include <iostream>
#define PI 3.1415926535897932384626433832795
#define cos(x) cos((x)*(PI/180))
#define sin(x) sin((x)*(PI/180))
using namespace std;

int main() {

	//Variablen zur Berechnung der Firsthöhe
	//
	double HL, HB; //Hauslänge und Hausbreite
	double DU1, DU2, DU3, DU4; //Dachüberstände
	int SW; //Sparrenwinkel bzw. Dachlängenwinkel zum First
	int FW1, FW2, FW3, FW4; //Firstwinkel zur Berechnung der Grundlängen der Dachflächen
	int DN1, DN2, DN3, DN4; //Dachneigung
	double hFirst; //Firsthöhe
	double FL; //Firstlänge

	int WinkelDL2, WinkelDL4; //Gratschifter-Winkel, d.h. Winkel zwischen GS2 (GS4) und hFirst
	double TLsegment2, TLsegment4; //Trapezseite: Teil der Trauflänge; 1x vom Querschnitt des Trapez (2), 1x von den Oberflächen des Trapez (4)
	double TL1, TL2, TL3, TL4; //Trauflänge
	double GTL; //Trauflänge gesamt
	double DL1, DL2, DL3, DL4; //Dachlängen
	double GLDF1, GLDF2, GLDF3, GLDF4; //Grundlängen der Dachflächen
	double GDL1, GDL2, GDL3, GDL4, GGDL; //Gratdachlänge bzw. Gratsparrenlänge

	//Variablen zur Berechnung der Dachoberflächen
	double GL1, GL2, GL3, GL4, GGL; //Gratlängen, Gesamtgratlänge
	double DF1, DF2, DF3, DF4, GDF; //Dachfläche, Gesamtdachfläche
	double DUL1, DUL2, DUL3, DUL4; //Dachüberstandslänge (Grund der Traufe)
	double GHL; //Hausumfang
	
	//////////////////////
	//Eingabe////////////
	/////////////////////
	//
	
	cout << "EINGABE DER WERTE" << endl;
	cout << "Hauslaenge: ";
	cin >> HL;
	cout << "Hausbreite: ";
	cin >> HB;
	cout << "Dachneigung 1: ";
	cin >> DN1;
	cout << "Dachneigung 2: ";
	cin >> DN2;
	cout << "Dachneigung 3: ";
	cin >> DN3;
	cout << "Dachneigung 4: ";
	cin >> DN4;
	cout << "Dachueberstand 1: ";
	cin >> DU1;
	cout << "Dachueberstand 2: ";
	cin >> DU2;
	cout << "Dachueberstand 3: ";
	cin >> DU3;
	cout << "Dachueberstand 4: ";
	cin >> DU4;
	
	///////////////////
	//VERARBEITUNG/////
	///////////////////
	//
	//OHNE DACHÜBERSTÄNDE
	
	//entspricht Hauslänge und Hausbreite
	GHL = HL * 2 + HB * 2; //gesamt

	//Sparrenlänge berechnen
	SW = 180 - (DN1 + DN3);					//Sparrenwinkel (oben am First zu den Sparren)
	DL1 = (sin(DN3) * HB) / sin(SW);
	hFirst = sin(DN1) *  DL1;				//Länge für Stütze unter dem First ermitteln
	DL2 = (hFirst * sin(90)) / sin(DN2);
	DL3 = (sin(DN1) * HB) / sin(SW);
	DL4 = (hFirst * sin(90)) / sin(DN4);

	//Grundlängen der Dachflächen
	FW1 = 180 - (90 + DN1);						//Firstwinkel, die oberen des Grunddreiecks der Dachfläche
	FW2 = 180 - (90 + DN2);
	FW3 = 180 - (90 + DN3);
	FW4 = 180 - (90 + DN4);
	GLDF1 = (hFirst * sin(FW1)) / sin(DN1);	
	GLDF2 = (hFirst * sin(FW2)) / sin(DN2);
	GLDF3 = (hFirst * sin(FW3)) / sin(DN3);
	GLDF4 = (hFirst * sin(FW4)) / sin(DN4);

	//Länge der Firstdachsteine ermitteln
	FL = HL - (GLDF4 + GLDF2);

	//Länge der Gratdachsteine ermitteln     
	GDL1 = sqrt(DL1*DL1 + GLDF1*GLDF1);
	GDL2 = sqrt(DL2*DL2 + GLDF2*GLDF2);
	GDL3 = sqrt(DL3*DL3 + GLDF3*GLDF3);
	GDL4 = sqrt(DL4*DL4 + GLDF4*GLDF4);
	GGDL = GDL1 + GDL2 + GDL3 + GDL4; //gesamt

	//Quadratmeter für Dachsteine ermitteln
	DF1 = ((TL1 + FL) * DL1) / 2;
	DF2 = (TL2 * DL2) / 2;
	DF3 = ((TL3 + FL) * DL3) / 2;
	DF4 = (TL4 * DL4) / 2;
	GDF = DF1 + DF2 + DF3 + DF4;			//Quadratmeter für Unterspannbahn ermitteln

	///////////
	//Ausgabe//
	///////////
	
	cout << "\n\n";
	cout << "Trauflaenge 1: " << TL1 << endl;
	cout << "Trauflaenge 2: " << TL2 << endl;
	cout << "Trauflaenge 3: " << TL3 << endl;
	cout << "Trauflaenge 4: " << TL4 << endl;
	cout << "Trauflaenge gesamt: " << GTL << endl; //Dachrinnenlänge berechnen

	cout << "Gratlaenge 1: " << GDL1 << endl;
	cout << "Gratlaenge 2: " << GDL2 << endl;
	cout << "Gratlaenge 3: " << GDL3 << endl;
	cout << "Gratlaenge 4: " << GDL4 << endl;
	cout << "Gratlaenge gesamt: " << GGDL << endl; //Länge für Gratdachsteine ermitteln

	cout << "Dachlaenge 1: " << DL1 << endl;
	cout << "Dachlaenge 2: " << DL2 << endl;
	cout << "Dachlaenge 3: " << DL3 << endl;
	cout << "Dachlaenge 4: " << DL4 << endl; //Sparrenlaenge berechnen

	cout << "Grundlaenge Dachflaeche 1: " << GLDF1 << endl;
	cout << "Grundlaenge Dachflaeche 2: " << GLDF2 << endl;
	cout << "Grundlaenge Dachflaeche 3: " << GLDF3 << endl;
	cout << "Grundlaenge Dachflaeche 4: " << GLDF4 << endl; //für weitere Berechnungen

	cout << "Firstlaenge: " << FL << " Meter" << endl; //Länge für Firstdachsteine ermitteln
	cout << "Firsthoehe: " << hFirst << " Meter" << endl; //Länge für Stütze unter dem First ermitteln
	cout << "Dachflaeche 1: " << DF1 << endl;
	cout << "Dachflaeche 2: " << DF2 << endl;
	cout << "Dachflaeche 3: " << DF3 << endl;
	cout << "Dachflaeche 4: " << DF4 << endl;
	cout << "Gesamtdachflaeche: " << GDF << endl;
Yes, now I have. It did not help me with what I am looking for.
What I figured though is that apparently one cannot use functions because they can only pass one value. I need THE THING to pass 100-200 values ;-)

Maybe I should take another, easier example, so everyone understands what I am looking for:

take a triangle, sides abc with height h, angles alpha, beta, gamma and add surface.

1
2
int alpha, beta, gamma;
double a, b, c, h, surface;


Now you want the program to calculate the surface for 2 types of triangles:

1) right-angled/perpendicular triangle --> beta = 90
2) non-right-angled triangle

You do not want to add a new variable but only use the surface variable for both calculations.
You want to output both results at the end.

Hi,

If you really want to use surface or hFirst variable for multiple calculations you may use arrays (or better vectors)
closed account (48T7M4Gy)
@OP

Let's take it in steps.

If you have a roof truss or a whole frame and want to describe/pass the 2 or 3D roof geometry then this can be done by recording the node coordinates and connectivity (say) using an array(s) or as shadder mentions as a vector(s).

Framing member properties can also be attributes of each member, part of which are the end coordinates.

Overall each framing member can be described as an object of a class or struct. Classes and structs are terms you need to review/learn about.

A whole group of members in the form of an array or vector can be passed as a function parameter. 1000's at a time - the only limitation is you computers capacity.

All the items you define in lines 12 to 32 or thereabouts can be encapsulated by a simple struct type or class and sent as a single instance (object) of that type as a single parameter in a function. But, have no fear, functions can pass many, many separate items of varied types as parameters.

(Structural analysis programs work this way and unless I'm mistaken, yours has strong similarities to parts of that type of work.)

take a triangle, sides abc with height h, angles alpha, beta, gamma and add surface.

Data overload. Only a fraction of those are required as input data; the others can be computed. If you do have more than a minimum amount of data as input, then you are open to inconsistent input.

For example: a=b=c=6, h=12, alpha=90, beta=60 and gamma=45 makes a sad panda, or at least a very bad triangle. Unless you disagree?

See: https://www.mathsisfun.com/algebra/trig-area-triangle-without-right-angle.html


You can have a function that calculates area from sides:
double heron( double a, double b, double c );

And then call it with different input:
1
2
surface = heron( 6, 6, 6 );
surface = heron( 3, 5, 4 );

The problem on that two-liner is that the second line overwrites the value stored in surface before that value is used. However, you could use the value before the second call to heron().

For example:
1
2
3
4
5
double area = 0.0;
for ( int a = 6; a < 10; ++a ) {
  area = heron( a, 3, 8 );
  std::cout << area << '\n';
}


Put in different way: a variable that is for storing one number can store exactly one number. It can store different value at different times, but it cannot store more than one value simultaneously.

An array or structure can store multiple values simultaneously, because they have been defined to store multiple values simultaneously.


1 the surfaces and lengths WITH ROOF OVERHANG
2 the surfaces and lengths WITHOUT ROOF OVERHANG

Ok, lets do:
double heron( double a, double b, double c, double overhang );
And use it:
1
2
area = heron( 3, 5, 4, 0 ); // uses overhang of 0.0, i.e. without overhang
area = heron( 3, 5, 4, 1 ); // with overhang of 1.0 


Alternatively, you could have two two different functions. If the area of overhang can be computed independently, then the implementation of the overhang version could use the without version:
1
2
3
4
5
double heron( double a, double b, double c, double overhang ) {
  double inside = heron( a, b, c ); // the area without overhang
  double outside = ... // whatever it takes
  return inside + outside;
}
I absolutely do not want to use 2 different variables for each value/(intermediate) result.
You do not want to add a new variable but only use the surface variable for both calculations.

OK, you've made yourself very clear that you can use only one variable but what you've left unstated is the type of variable that you can use. How much flexibility do you have in using a data-type like pair<double,double> for the surface variable. If you can do that, your triangle area calculation would like like this:

(notation reference off the first triangle here:http://www.se16.info/hgb/triangle.htm)
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
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

constexpr auto PI = 3.14159;

using param = const double&;

pair<double, double> triangle_area(param a, param b, param h, param angleB, param angleC);

int main()
{

}
pair<double, double> triangle_area(param a, param b, param h, param angleB, param angleC)
{
    pair<double,double> surface;
    if(angleB == 90)
    {
        surface.first = (0.5)*(a)*(h);
    }
    else
    {
        surface.second = (a)*(b)*sin(angleC*PI/180);
        //double-check my high-school trigo
    }
    return surface;
}

From pair you can go to tuple, vector etc to capture larger # of returns from the same function
Hi,

Just some other questions and advice to help you out:


.... (around 200 when the program is finished) and saves the results in the corresponding variables

What do you mean by this - how do you have 200 distances? Are there multiple, maybe unknown number of roofs to calculate?

I think the word surface is not quite the right translation in English - do you mean Area?

Did you know that given a PlanArea and a consistent RoofPitch, then double SlopeArea = PlanArea / cos(RoofPitch);

Avoid using #define statements for variables and macros. Make the variables const like gunnerfunner has done. Make the macros actual functions. It can be a particular problem to have a macro that redefines the name of a library call like sin().

Give your function and variables good names, there is no need to abbreviate everything. If this is done very well the code should be self documenting - like reading a story of what is happening. For example Trauflange instead of TL. Use a std::vector or a std::array instead of TL1, TL2, TL3, TL4

Avoid where possible declaring your variables until you a sensible value to assign to them. This avoids problems associated with not initialising variables and is easier to understand.

I always put digits before and after the decimal point for double values - this reinforces the idea that the value is a double, and often helps ensure that the result of the expression will be double. So 180 would be 180.0. Also avoids implicit casting by the compiler.

Finally, something most beginners do, but perhaps a good idea to learn the lesson early: Avoid using namespace std; Believe me, in the end it is better to just put std:: before each std thing. There is a lot written on this forum, and on the internet as to why this particular using statement can be bad. Also if you look at code done by experts such as JLBorges, they always have std::

Good Luck !!
closed account (48T7M4Gy)
Using structs:

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
#include <iostream>
#include <cmath>

struct HipRoof
{
    double length;
    double width;
    double angle; // degrees
    
    HipRoof();
    HipRoof(double aLength, double aWidth, double aAngle)
    {
        length = aLength;
        width = aWidth;
        angle = aAngle;
    }
    
    double rise() const { return width * tan(angle * M_PI /180) / 2; };
    double common_rafter_length() const { return width / 2 / cos( angle * M_PI /180); };
    double ridge_board_length() const { return length - width;};
    double hip_rafter_length() const { return sqrt( width * width / 2 + (rise() * rise() )) ;};
    double area() const { return width * length / cos( angle * M_PI /180); }
    
    friend std::ostream& operator<< (std::ostream& os, const HipRoof &rhs)
    {
        os
        << "                Rise: " << rhs.rise() << '\n'
        << "Common rafter length: " << rhs.common_rafter_length() << '\n'
        << "  Ridge board length: " << rhs.ridge_board_length() << '\n'
        << "   Hip rafter length: " << rhs.hip_rafter_length() << '\n'
        << "                Area: " << rhs.area() << '\n';
        
        return os;
    };
};



int main()
{
    HipRoof roof_1( 20, 10, 10);
    std::cout << roof_1 << '\n';
    
    for (int slope = 5; slope < 10; slope++)
    {
        roof_1.angle = slope;
        std::cout << "Angle: " << slope << '\n' << roof_1 << '\n';
    }
    
    HipRoof xyz(38.207, 22.109, 15.2);
    std::cout << xyz << '\n';
    
    return 0;
}
 Rise: 0.881635
Common rafter length: 5.07713
  Ridge board length: 10
   Hip rafter length: 7.12582
                Area: 203.085

                Rise: 3.00344
Common rafter length: 11.4552
  Ridge board length: 16.098
   Hip rafter length: 15.9193
                Area: 875.341

Program ended with exit code: 0
Last edited on
Topic archived. No new replies allowed.