I'm writing a program that calculates the distance traveled when an object is thrown straight up with a given speed.
Now I need to implement angles to see how that affects the height loss per second compared to when it is thrown straight up.
I was told to use the math library but I have no idea from where to go from here.
//The following calculation can be used to calculate the correlation between time and height
//h(t )=−0.5⋅G⋅t^2+V⋅T+H
#include <iostream>
#include <limits>
using namespace std;
int main() {
//Falling speed
const double G = 9.81;
//Starting height
double H = 0;
//Velocity/Speed
double V = 0;
//End product
double Ht = 0;
//Seconds that result is displayed on the screen
double T = 0;
//t^2
double Tt = 0;
int S;
int s = 1;
cout << "\nGive me the starting height: ";
while(!(cin >> H)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "False input. Try again: ";
}
cout << "\nGive me the starting speed: ";
while(!(cin >> V)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "False input. Try again: ";
}
cout << "\nHow often do you want the current height to be displayed (In seconds)\n";
while(!(cin >> S)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "False input. Try again: ";
}
for (int i = 0; i < 10; i = i + S) {
Tt = i*i;
Ht = -0.5 * G * Tt + V * i + H;
if (Ht >= 0){
cout << "Second " << s << " the height is " << Ht << " Meters" << endl;
s += 1;
} else {
Ht = 0;
cout << "Second " << s << " the height is " << Ht << " Meters" << endl;
i = 9;
}
}
}
Any help is appreciated.
You are starting out in the right direction, but you are stumbling into a few pitfalls trying to implement "special cases" to keep your arithmetic sign correct. Don't do that. In kinematics and dynamics every position, velocity or acceleration is relative to the coordinate system you choose. If you are consistent with your vector direction -- you never have to worry about a special case again.
Huh? What do you mean?
Take your gravity term, const double G = 9.81;. Unless you have defined the Y coordinate as positive in the down direction, your sign on G is wrong (pitfall...). Most normal cartesian coordinates systems have Y as positive up (screen coordinates and aircraft body coordinates are exceptions). With the Y axis positive-up, what direction does gravity act in? (if confused, "drop a rock" -- advise from one of my old profs :)
Gravity acts in the downward direction and therefore should be declared as a negative value with Y positive-up. Since as your code grows, virtually all calculation functions will need that term, so you may as well make it global:
static const double G = -9.81; /* global constant is fine, pay attention to sign */
Then for every position calculation you make based on acceleration and time simply uses the standard formula:
X = Xo + Vo * t + 0.5 * a * t * t;
No need to go inserting spurious '-' signs in the calculation or splitting out special cases for output. As you add forces that act on your projectile keeping your force directions straight becomes critical. All forces are vector quantities and have a direction. If you always attribute the correct direction to each force, you never have to adjust a formula or worry about a special case again.
For your calculations that means you can simply use:
for (int i = 0; i < 15; i = i + S) {
double Tt = i * i, /* seconds squared */
Ht = H + V * i + 0.5 * G * Tt, /* pos based on acceleration & time */
Vt = V + G * i; /* vel based on acceleration & time */
...
(note: the base number of iterations was increased to 15 which is what is needed to adequately see the height reversal for objects fired upward at 100 m/s or less -- any faster and atmospheric compressability becomes a factor)
Consider a Continual Loop for Input
When you want to require the user to provide valid input, it is more convenient to use a continual loop and break the read-loop when your conditions are satisfied. (This allows you to fully contain the prompt and error reporting within the loop). For example, you could do:
while (true) { /* loop continually until valid input (prompt within) */
std::cout << "\nStarting height : ";
if (std::cin >> H)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "False input. Try again: "; /* error output on cerr */
}
(note: Good job on properly using std::cin.ignore(), you may also want to distinguish between eofbit and failbit being set later on, but you do a good job of validation)
After the final input, you can add a std::cout.put ('\n'); to provide a newline separating the input and output values.
Putting that altogether for your example, and saving the formatting flags for std::cout and then setting fixed output with a precision of 2 you could do:
#include <iostream>
#include <iomanip>
#include <limits>
static const double G = -9.81; /* global constant is fine, pay attention to sign */
int main () {
double H = 0; /* starting height */
double V = 0; /* initial velocity */
int S; /* time step (seconds) */
while (true) { /* loop continually until valid input (prompt within) */
std::cout << "\nStarting height : ";
if (std::cin >> H)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "False input. Try again: "; /* error output on cerr */
}
while (true) {
std::cout << "Starting speed : ";
if (std::cin >> V)
break;
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "False input. Try again: ";
}
while (true) {
std::cout << "Time Step (In seconds) : ";
if (std::cin >> S) {
std::cout.put ('\n'); /* tidy up with additional newline */
break;
}
std::cin.clear();
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
std::cerr << "False input. Try again: ";
}
std::ios_base::fmtflags f = std::cout.flags(); /* save format flags */
std::cout << std::fixed; /* set fixed precision */
std::cout.precision(2); /* of 2 */
for (int i = 0; i < 15; i = i + S) {
double Tt = i * i, /* seconds squared */
Ht = H + V * i + 0.5 * G * Tt, /* pos based on acceleration & time */
Vt = V + G * i; /* vel based on acceleration & time */
std::cout << "Second: " << std::setw(3) << i
<< " Height: " << std::setw(6) << Ht
<< " Velocity: " << std::setw(6) << Vt << '\n';
}
std::cout.flags(f); /* restore default precision */
}
(note: there are no "special cases" in the computations or in the output formatting. Also consider making S type double so you can enter, e.g. .2 or .1 as the time step for finer granularity in your output. You can also add input for StartTime and StopTime which would allow extremely fine-grained examination of output over short (or long) time periods)
Example Use/Output
If you take for example a projectile with an initial height of 10 meters and an initial upward velocity of 100 m/s, you can observe where the velocity decreases to zero and then beginning increasing as it falls back to earth. You will see the like reversal in height.
$ ./bin/kinematic_h+v
Starting height : 10
Starting speed : 100
Time Step (In seconds) : 1
Second: 0 Height: 10.00 Velocity: 100.00
Second: 1 Height: 105.09 Velocity: 90.19
Second: 2 Height: 190.38 Velocity: 80.38
Second: 3 Height: 265.86 Velocity: 70.57
Second: 4 Height: 331.52 Velocity: 60.76
Second: 5 Height: 387.38 Velocity: 50.95
Second: 6 Height: 433.42 Velocity: 41.14
Second: 7 Height: 469.65 Velocity: 31.33
Second: 8 Height: 496.08 Velocity: 21.52
Second: 9 Height: 512.69 Velocity: 11.71
Second: 10 Height: 519.50 Velocity: 1.90
Second: 11 Height: 516.50 Velocity: -7.91
Second: 12 Height: 503.68 Velocity: -17.72
Second: 13 Height: 481.05 Velocity: -27.53
Second: 14 Height: 448.62 Velocity: -37.34
If you wanted a time step of two, you would do:
$ ./bin/kinematic_h+v
Starting height : 10
Starting speed : 100
Time Step (In seconds) : 2
Second: 0 Height: 10.00 Velocity: 100.00
Second: 2 Height: 190.38 Velocity: 80.38
Second: 4 Height: 331.52 Velocity: 60.76
Second: 6 Height: 433.42 Velocity: 41.14
Second: 8 Height: 496.08 Velocity: 21.52
Second: 10 Height: 519.50 Velocity: 1.90
Second: 12 Height: 503.68 Velocity: -17.72
Second: 14 Height: 448.62 Velocity: -37.34
(note: to solve for the exact time when the projectile reaches its maximum height, simply set the final velocity to 0 in your normal V = Vo + a * t equation and solve for t, e.g. t = -Vo / a. Here is a nice Kinematics calculator - Physics Catalyst that also provides the nuts and bolts equations of motion for your use.)
Lastly, have a look at Why is “using namespace std;” considered bad practice?. Building good habits early is a lot easier than breaking bad ones later...
Moving to 3-Dimensional Space
There is virtually no difference in how you approach a 3-Dimensional problem. Instead of using H and V is becomes easier to use a struct that holds the double x, y, z; coordinates and velocities. Then your functions simply operates on the x, y and z members independently using the very same formulas. Then for the final values just square-root of the sum of the squares and atan2() for resulting angles.
Additionally, when working in 3-Dimensions, you can make use of the vector Dot and Cross products, which become increasingly useful as you beginning working with angular rates and measures.
Look things over and let me know if you have further questions.
Related
I'm trying to write a script where the user will be inputting a radius and then the console will display the Volume and Surface Area of a sphere. If the input radius is negative, the user will be prompted to enter a positive radius until the condition is met. I've managed to do this but without validating the positive radius bit. How can I achieve this?
My code:
/*
* Calculate the volume and surface area of a sphere.
*
*/
#include <iostream>
#include <string>
#include <sstream>
#include <cmath> // Include cmath for M_PI constant
using namespace std;
int main()
{
const double pi = M_PI; /// Value of PI defined by C++
string input = ""; /// Temporary input buffer
double r = 0.0; /// Sphere radius
double A = 0.0; /// Sphere area
double V = 0.0; /// Sphere volume
// Request radius
cout << "Please enter radius of sphere (positive only): ";
// Get string input from user (up to next press of <enter> key)
getline(cin, input);
// Try to convert input to a double
r = stod(input);
// making sure r is positive
if (r > 0)
{
// Calculate area and volume
// Ensure floating-point division instead of integer division by
// explicitly writing 4.0/3.0
A = 4.0 * pi * r * r;
V = (4.0 / 3.0) * pi * r * r * r;
// Write out result
cout << "Sphere radius: " << r << endl;
cout << "Sphere area: " << A << endl;
cout << "Sphere volume: " << V << endl;
}
else
{
while (r < 0)
{
cout << "Please enter radius of sphere (positive only): " << endl;
}
}
// Return success
return 0;
}
First, this code is not awful. Compared to what I've seen from some other beginners, this code demonstrates that there is a decent understanding of fundamentals up to this point.
The biggest issue facing your code is the order of operations. If you want input from the user, you need to validate it before processing it. Currently, you're doing a bit of both at the same time. As mentioned, create a loop that does not exit until you have valid inputs. Then go ahead and do your math. This is separating your concerns and is a best practice.
Other nitpicks include using namespace std; as a bad practice, and one you should get out of doing sooner than later. Front-declaring your variables is also bad practice. Declare at or near first use. std::string input; suffices for a default string, there is no need to = "";.
And as I commented, stod() can throw an exception and abort your program if the input cannot be converted. You don't mention whether you're allowed to assume your input will always be a number or not so I can't assume it is.
/*
* Calculate the volume and surface area of a sphere.
*
*/
#include <cmath>
#include <iostream>
#include <numbers>
#include <string>
int main() {
double radius = 0.0;
bool inputIsInvalid = true;
do {
std::string input;
std::cout << "Enter a radius: ";
std::getline(std::cin, input);
std::size_t pos = 0;
try {
radius = std::stod(input, &pos);
} catch (const std::exception& e) {
std::cerr << "Unable to convert to double. Reason: " << e.what() << '\n';
continue;
}
// We're still not done checking. We need to ensure that the entire string
// was converted. If not, the input was invalid.
if (pos != input.length()) {
std::cerr << "Invalid characters added. Try again.\n";
continue;
}
// Making it here means a valid double was typed in.
// Now we ensure that the double is positive.
if (radius < 0.0) {
std::cerr << "Please enter a positive number. Try again.\n";
continue;
}
// Making it here should mean that we have a valid input.
inputIsInvalid = false;
} while (inputIsInvalid);
// Now we can do math!
using namespace std::numbers; // C++20 stuff for pi
double surfaceArea = 4.0 * pi * std::pow(radius, 2);
double volume = (4.0 / 3.0) * pi * std::pow(radius, 3);
std::cout << "For a sphere of radius: " << radius << '\n'
<< "Surface area: " << surfaceArea << '\n'
<< "Volume: " << volume << '\n';
}
Output:
❯ ./a.out
Enter a radius: foo
Unable to convert to double. Reason: stod: no conversion
Enter a radius: 3o
Invalid characters added. Try again.
Enter a radius: -3
Please enter a positive number. Try again.
Enter a radius: 3
For a sphere of radius: 3
Surface area: 113.097
Volume: 113.097
As you can see, all of the getting of input and validation occurs within the big do/while loop. If we are out of the loop, we know that we have a valid value, and doing the math is now very straightforward.
There is no need for complicated statements.
You just need to understand that IO operation notice, when there was a problem. And then they set failure bits, which you can check.
Please look in the CPP reference at this link. There is a long description of what could happen and what failure bit will be set and how it can be tested.
So, if you use for example the stand extraction operator >> like in std::cin >> radius then this operator will try to read a value from the console and convert it to a double. If it cannot do that, because you entered for example "abc" instead of a number, a failure bit will be set. The std::cinis then in state fail and does not work any longer.
If you want to continue to use std::cin then you must clear the fail bits with the clear() function. So, you need to write std::cin.clear();.
But this is not sufficient. There might be still some other characters in the input buffer. And those need to be removed. Imagine that you enter "XYZ" instead of a number, then std::cin will go into failure state after reading the first character 'X'. We need to eliminate all the wrong characters, because otherwise, they will be read again with the next >> operation.
For this we have the function ignore. Please read here about the function and look at the example at the bottom of the page. Exactly what you need.
Next: How can we check for an error of an IO operation?
You may have heard that we can chain IO operations. For example: int a,b; std::cin >> a >> b; or, for the output case std::cout << value << "\n";
Why does this work? You need to understand the the extraction and inserter operator >> and << return a reference to the stream for which they have been called.
So, std::cin >> a; will return a reference to std::cin. And that is the reason why you can chain IO operations.
std::cin >> a >> b; will first do std::cin >> a which will return std::cin. The rest of the expression will now be std::cin >> b;. also this will be performed and again std::cin will be returned.
And this we can use. The basic:ios has 2 operators to check the failure state.
the bool operator
the not operator !
So, you can check the state of std::cin simply with if (std::cin). And because the if-statement expects a bool expression, it will call the streams bool operator. And with that get the state.
And now, what we learned above: if (std::cin >> a) will try to read a value into "a" then return std::cin and then its bool operator is called.
Now we found a possibility to check for a correct IO operation with if (std::cin >> radius) But of course we can do more test in the if statement. You have often seen and && or or|| operators in conditions. You can make use of it. And especially you can make use of boolean shortcut evaluation.
Meaning, if the outcome of a condition is already clear by evaluation the first term, then the second term will not be evaluated.
So, we can write if ((std::cin >> radius) and (radius > 0.0)) to check for a valid input. If the reading of the input fails, then the check for greater than 0 will not be executed. It will only be executed, if the input was successful.
With all the above, we can now draft the below very simple solution:
#include <iostream>
#include <limits>
int main() {
double radius = 0.0;
bool valueOK = false;
while (not valueOK) {
std::cout << "\n\nInsert radius. A positive value: ";
if ((std::cin >> radius) and (radius > 0.0))
valueOK = true;
else {
std::cout << "\n\n***Error: invalid input\n";
}
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
const double PI = 3.14159265358979323846;
std::cout << "\n\nSphere Radius:\t" << radius
<< "\nSphere area:\t" << 4.0 * PI * radius * radius
<< "\nSphere volume:\t" << 4.0 / 3.0 * PI * radius * radius * radius << '\n';
}
No need for complicated statements.
You could use std::from_chars within an infinite loop to read a radius of type double (see here):
It receives a couple of const char* to the beginning and end of the string you want to parse, and a reference to a double value (that will be set if the parsing went OK).
It returns a pointer pointing to the first character that didn't match the pattern for a double value, and an error.
If the error is "empty" (just value-initialized), and the pointer points to the end of the input string, it means that all the characters were used to parse the double value (i.e. there were no extra characters at the beginning or at the end in the input string).
[Demo]
#include <charconv> // from_chars
#include <iostream> // cin, cout
#include <numbers> // Include cmath for M_PI constant
#include <sstream>
#include <string> // getline
#include <system_error> // errc
int main() {
// Request radius
double r = 0.0; /// Sphere radius
for (;;) {
std::cout << "Please enter radius of sphere (positive only): ";
// Get string input from user (up to next press of <enter> key)
std::string input = ""; /// Temporary input buffer
getline(std::cin, input);
std::cout << input << "\n";
// Try to convert input to a double
auto [ptr, ec] = std::from_chars(input.data(), input.data() + input.size(), r);
if (ec != std::errc{} or ptr != input.data() + input.size() or r < 0) {
std::cout << "Invalid input: '" << input << "'\n";
} else {
break;
}
}
// Calculate area and volume
// Ensure floating-point division instead of integer division by
// explicitly writing 4.0/3.0
double A = 4.0 * std::numbers::pi_v<double> * r * r; /// Sphere area
double V = (4.0 / 3.0) * std::numbers::pi_v<double> * r * r * r; /// Sphere volume
// Write out result
std::cout << "Sphere radius: " << r << "\n";
std::cout << "Sphere area: " << A << "\n";
std::cout << "Sphere volume: " << V << "\n";
// Return success
return 0;
}
// Outputs:
//
// Please enter radius of sphere (positive only): -5
// Invalid input: '-5'
// Please enter radius of sphere (positive only): hola
// Invalid input: 'hola'
// Please enter radius of sphere (positive only): 25abc
// Invalid input: '25abc'
// Please enter radius of sphere (positive only): 1.5
// Sphere radius: 1.5
// Sphere area: 28.2743
// Sphere volume: 14.1372
This question already has answers here:
Accessing an array out of bounds gives no error, why?
(18 answers)
Closed 7 months ago.
data11.txt:
Length(l) Time(t) Period(T)
200 10.55 0.527
300 22.72 1.136
400 26.16 1.308
500 28.59 1.429
600 31.16 1.558
ill be taking data from this file above in my code
#include <iostream>
#include <cmath>
#include <fstream>
#include <string>
#include <iomanip>
/*Using data11.txt as reference, write code to read from the file. In a pendulum experiment certain data was recorded in order to calculate the acceleration due to gravity. All calculations should be in their SI units
Write a function to calculate the acceleration due to gravity as the slope of the graph to this equation.T=2πlg−−√.
What is the percentage error in your calculated value? Take g=9.8ms-2.
If the pendulum weighs 50g and is displaced at an angle of 30, what will it maximum kinetic energy value for each length of the string? Display your answer in table form. */
using namespace std;
double slope_gravity(double T1, double T2, double L1, double L2){//slope function
double T1_inverse = 1/pow(T1,2);
double T2_inverse = 1/pow(T2,2);
double difference_T = T2_inverse - T1_inverse;
double difference_L = (L2 - L1)/100;
double slope = (difference_T/difference_L);
return slope;
}
const int n = 4;
int main (){
ifstream mydata;
string capture;
float Length[n], Time[n], Period[n], acc_gravity;//declaring variable
mydata.open("Data11.txt");
if (mydata.is_open()){
for (int i=0; i<n+1; i++){
getline(mydata, capture);
mydata >> Length[i] >> Time[i] >> Period[i];
}
acc_gravity = slope_gravity(Period[1], Period[0], Length[1], Length[0]);//acceleration due to gravity calc
cout << fixed << showpoint << setprecision(1);
cout << "The Acceleration Due To Gravity Obtained Experimentally "
<< "from the data11 file is "<<abs(acc_gravity)<<"ms^-2"<<endl;
cout << "Calculating for Percentage error.............";
cout <<endl<<endl;
float percent_error = (abs(acc_gravity)- 9.8) * 100/9.8;//error analysis
cout << "Percent Error is "<< setprecision(2) << abs(percent_error)<<"%"<<endl;
cout << endl;
cout << "Calculating Max Kinetic Energy of pendulum weighing 50g being "
<< "displaced at an angle of 30\n";
cout << setprecision(4);
float velocity[n], x[n], y;//kinetic energy calc
double max_KE[n];
for (int j=0; j<n+1; j++){
x[j] = 2 * acc_gravity * Length[j]/100;
y = 1 - cos(30);
velocity[j] = sqrt(x[j] * y);
max_KE[j] = 0.5 * 50/1000 * pow(velocity[j],2);
}
cout<<endl<<endl;
cout << setprecision(1);
cout << "Length(m)\tMaximum Kinetic Energy(J)\n";//tabular form display
for (int k=0; k<n+1; k++){
cout << Length[k] <<"\t"<< max_KE[k] <<endl;
}
}
mydata.close();
return 0;
}
The objective of the program is in the first comment above.
At the end of the program, i'm supposed to print the values of length and Maximum Kinetic energy to the console in a tabular form.
However, in the array Length[0], it prints 31.16, but i extracted data from data11.txt, so there is supposed to be the value 200 instead.
The origin of the problem start with this for loop. The for loop works well by extracting values from data11.txt. so the value of Length[0] is 200 here.
i've tried to check why it is behaving this way. The problem starts here;
mydata.open("Data11.txt");
if (mydata.is_open()){
for (int i=0; i<n+1; i++){
getline(mydata, capture);
mydata >> Length[i] >> Time[i] >> Period[i];
}
But outside the forloop, Length[0] is 31.16. I also noticed that Time[4] has different value from input value which is supposed to be 31.16.
Please any help with this?
What you have noticed is called 'buffer overrun'.
float Length[n], Time[n], Period[n], acc_gravity;
// since 'n' is 4,
// so the valid range of subscript of Length/Time/Period are [0-3]
// That means, if you try to write to Length[4],
// that is invalid, often lead to ruin something else.
mydata.open("data11.txt");
if (!mydata.is_open())
{
fprintf(stderr,"failed to open datafile.\n");
return 1;
}
for (int i=0; i<n+1; i++){ // here the rang of 'i' is [0 - 4]
getline(mydata, capture);
mydata >> Length[i] >> Time[i] >> Period[i]; // so, when i==4,
// 'buffer overun' happens here.
// 'Time' could be ruined by 'Period'.
}
If you want to skip the 'header' line of input file,
one possible approach is :
"'getline()' once , then enter the loop".
Whatever you choose, just don't 'buffer overrun'.
Good luck.:)
I'm new to c++ so what I like to do is make numerous calculators of anything, varying from area calculators to quadradic formula and etc. Anyways I'm creating a triangle area calculator but there is one small problem but first here's my code:
#include <iostream>
#include <cmath>
using namespace std;
int triangle()
{
int base;
int height;
int area;
cout << "Enter base: ";
cin >> base;
cout << "Enter height: ";
cin >> height;
area = base * height /2;
cout << area;
return area;
}
int main ()
{
cout << "Formula Calculator \n";
cout << triangle();
return 0;
}
The input is this:
Enter base: (I enter 4)
Enter height: (I enter 5)
1010
As you can see the 5 * 4 * 1/2 is not 10 for some reason every number that the area is, is always digit doubled if you know what I mean for ex if the area is 20 the program will show 2020, please help.
You output the area twice.
cout << area; // here's once
cout << triangle(); // here's twice
I would suggest rethinking your code. Should the triangle function just compute the area or should it ask for input and do output? If the latter, why cout << triangle();?
When you are inside your function triangle(), check it's 2nd last line, It is cout<<area, let's say you have given input 4 and 5 so inside the body of the function, at cout<<area it will output the area. Now it returns area which is then outputted by 2nd last line of your program i.e cout<< traingle()//return value is outputted so that's why we are seeing 2 outputs. It is not only in the case of 4 and 5, but it will also output area 2 times in every case.
c++ and I'm trying to figure out why my code returns 0's from a few statements after the user inputs some float numbers. I'm not sure why. Maybe someone can help:
This is what I get after running my method and answering the questions before it:
The number of gallons of paint required is: 0 gallons
Hours of labor that is required: 0 hours
.
Also ignore the () around my # in the beginning. I will put periods between lines to make it look neater on this website.
/**
* A painting company has determined that for every 160 square feet of wall
space, one gallon of paint and 3 hours of labor are required.
* The company charges the $28.00 per hour for labor.
* Design a modular program that allows the user to enter the number of rooms
that are to be painted,
* the approximate square feet of wall space in each room (may differ from room
to room), and the price per gallon of paint.
* It should then create a report that includes a fancy company header and
displays the following information:
* The number of gallons of paint required: (Rounded up to the next full
gallon)
* The hours of labor required:
* The cost of the paint:
* The labor charges:
* Total cost of the paint job:
* Requirements:
* Input validation: The program should not accept a value less than 1 or
more than 12 for the number of rooms
* Should not accept a value less than 100 for the square
footage of a room.
* Should not accept a value less than $10.00 or more
than $25.00 for the price of a gallon of paint
*
* Lets do this...
*/
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
float priceOfGallon(float);
float numberOfGallons(float, float);
float totalWallArea(float, float, float);
float laborHours(float, float);
void fancyCompanyHeader();
int main() {
float area;
float totalArea;
float min_labor = 3;
float number_of_rooms;
float number_of_gallons;
float price_of_gallon;
totalWallArea(area, totalArea, number_of_rooms);
priceOfGallon(price_of_gallon);
numberOfGallons(number_of_gallons, totalArea);
laborHours(number_of_gallons, min_labor);
fancyCompanyHeader();
return 0;
}
// function that gets the number of gallons needed for the total area
float numberOfGallons(float number_of_gallons, float totalArea) {
number_of_gallons = (totalArea / 160.0);
std::cout << "The number of gallons of paint required is: " <<
number_of_gallons << " gallons" << std::endl;
}
float priceOfGallon(float price_of_gallon){
std::cout << "Please enter the price per gallon: " << std::endl;
cin >> price_of_gallon;
while(price_of_gallon < 10.00 || price_of_gallon > 25.00) {
std::cout << "The price should be between $10.00 and $25.00. Please try again: " << std::endl;
cin >> price_of_gallon;
}
}
float totalWallArea(float area, float totalArea, float number_of_rooms) {
std::cout << "Please enter the number of rooms that needs to be painted:" <<
std::endl;
std::cin >> number_of_rooms;
while(number_of_rooms < 1)
{
cout << "Number of rooms must be at least one. Please try again: " <<
std::endl;
cin >> number_of_rooms;
}
for(float i = 1; i <= number_of_rooms; i++)
{
cout << "Please enter the square feet of wall space needed for Room " <<
i << std::endl;
cin >> area;
while(area < 100)
{
std::cout << "The area should be 100 or greater. Please try again: "
<< std::endl;
cin >> area;
}
totalArea += area;
}
}
// I will finish this method later
float laborHours(float number_of_gallons, float min_labor) {
min_labor = number_of_gallons * 28.00;
std::cout << "Hours of labor that is required: " << min_labor << " hours "
<< std::endl;
return min_labor;
}
You need to make all of those variables you are modifying global (Declared outside of int main()). In C++, when you give a function a variable, it will just copy the contents of the variable into the function's variables: the original variable passed in remains constant. Thus, your uninitialized floats default to 0 and are not changed by any of the functions, so when they are given to the laborHours function or numberOfHours function, 0s are passed into each.
Example with much better practices than in your code (it's ok, everyone starts by writing atrocious code) :
#include <iostream>
int walls,rooms,total_walls; //It only makes sense if all of these are integers.
//These are global declarations, they can be modified by any function in the program
void input_walls() {
/* Functions are notated as so in C++:
{return type} {function_name}({input},{input},...)
It's pointless to annotate functions that don't return anything
with a declaration of a float return type (they'll just return 0 */
std::cin >> walls;
while(walls < 0) {
std::cout << "Please input a positive amount of walls per room.";
std::cin >> walls;
}
}
void input_rooms() {
std::cin >> rooms;
while(rooms < 0) {
std::cout << "Please input a positive amount of rooms";
std::cin >> rooms;
}
}
void calculate_result() {
total_walls = walls*rooms;
}
void output_result() {
std::cout << "I'll need to paint " << total_walls << " walls!" << std::endl;
}
int main() {
input_walls();
input_rooms();
calculate_result();
output_result();
}
This still isn't the best way to write this, but it's still the exact same thing you were trying to do. Now try rewriting what you were trying to do in this style!
TLDR/Quick fix: Make the variable definitions global, cut out the arguments from the functions.
I have a homework assignment that requires me to calculate a percentage chance from an user input of the numbers 1 to 3. However, I'm not sure how to do this.
This is my code, not all of it though:
void SwingAtBall( Ball *tBall ) {
std::cout << "How hard do you want to hit the ball? Please enter a number between 1 to 3." << std::endl;
int tBallHit;
std::cin >> tBallHit;
if ( tBallHit > 3 || tBallHit < 1 ) {
std::cout << "That is not a valid value. Please enter a number between 1 to 3." << std::endl;
std::cin >> tBallHit;
}
}
// Prompt for 1 to 3. There is a (input * 15) percent chance the ball only goes 5 feet. Otherwise the ball is hit a random number between 0 and (input * 150). Print how far it went.
If my understanding is correct that there is an (input * 15) percent chance the ball will go 5 feet and an (100 - (input * 15)) percent chance it will go anywhere from 0 to (input * 150) feet, then the following code will calculate what you are looking for...
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int inp, chance1, dist1, dist2, dist_final;
do {
cout << "Enter integer between 1 and 3: ";
cin >> inp;
} while (inp < 0 || inp > 3);
dist1 = 5;
srand(time(0));
dist2 = rand() % (inp * 150);
chance1 = (inp * 15) / 100;
dist_final = chance1 * dist1 + (1 - chance1) * dist2;
cout << "It went this far: " << dist_final << endl;
// system("pause");
return 0;
}
There's a whole <random> header for things like this.
Simple percentages are easy, you can use integers for that. Pick either 0-99 or 1-100, and use that in a uniform_int_distribution. Sure, 15% is 3/20 so you could also use a uniform_int_distribution(1,20) but that's more obscure.
"0 to (input * 150)" is a uniform_int_distribution(0,input*150).