Keep asking for user input until condition met C++ - c++

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

Related

Implementing angles into height-to-time calculation

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.

C++: Is there a way to distinguish a user input if its on centimeter or not?

Heres the given:
Write a program to compute for the surface area and volume of a sphere if the unit of the radius
is in centimeters (cm).
Filename: exer10.cpp
Formulas: area = 4*pi*radius2
Volume = (4/3)*pi*radius3
I was skeptical because of the "if" on the given as you read it, now I don't know if what I did is right. But I have some ideas on how to do it
I Have a 2 ideas in mind 1st is where if I input a value there will be a formula to distinguish if that value is in centimeter, the thing is I don't know how.
2nd idea is I will use the if else method where after I input a value, it will ask if its in centimeter or not, if I type "Y" it will do its thing and continue its computation but if I type "N" it`ll will not compute and end the program.
Any suggestion guys?
By the way here's my code (My given ideas are not written here)
#include <iostream>
using namespace std;
int main()
{
float radius, area, volume;
cout << "This program computes for the surface area and volume of a sphere (centimeters)"
"\n\n";
cout << "Input the radius of a sphere    : ";
cin >> radius;
area = (4 * 3.1416 * radius * radius);
volume = (4 / 3) * (3.1416 * radius * radius * radius);
cout << "The surface area of a sphere is : " << area << "\n";
cout << "The volume of a sphere is       : " << volume;
return 0;
}
You can ask the user to input the unit. Consider this example, if it's in centimeters then perform the operation/task or else exit the program.
#include <iostream>
#include <string>
#include <cstdio>
int main() {
int radius;
std::string unit;
std::cout << "Enter radius of sphere in centimeters (e.g. 5 cm) : ";
std::cin >> radius >> unit;
if (unit != "cm") {
std::cout << "\nPlease enter in centimeters (e.g. 5 cm)";
exit(1);
}
// perform operation
return 0;
}

C Plus Plus not calculating correctly

I made a program that calculates the area of a circle. You have the option to enter a diameter or a radius. After you select one of them, you enter the value. Then it tells you what you entered and gives you the answer. But the answer isn't correct. For example, I enter 'r' then type '3' it gives me:
This is a calculator that calculates the area of a circle.
To get started, type 'd' (no quotes or caps) to enter a diamater.
Type 'r' (no quotes or caps) to enter a radius.
r
You chose radius, now please enter a number.
3
3 * 2 * 3.14 = 40828.1
It doesn't look right, as you can see. Perhaps C++'s Pi variable is outdated?
#include <iostream>
#include <math.h> // Importing math.h so I can use the M_PI variable.
using namespace std;
int main() {
char choice;
float result = 0.0; // Set to zero to init and stop the IDE from complaining.
float number = 0.0;
cout << "This is a calculator that calculates the area of a circle." << endl;
cout << "To get started, type 'd' (no quotes or caps) to enter a diamater." << endl;
cout << "Type 'r' (no quotes or caps) to enter a radius." << endl;
cin >> choice;
choice = tolower(choice); // Making it lower case so it's easier for compiler to recoginize.
switch (choice) {
case 'r':
cout << "You chose radius, now please enter a number." << endl;
cin >> number;
result = choice*choice*M_PI;
break;
case 'd':
cout << "You chose radius, now please enter a number." << endl;
cin >> number;
result = choice*M_PI;
break;
default:
cout << "You entered an invalid character. Please only enter 'r' or 'd' (no quotes or caps)" << endl;
break;
}
if (choice == 'r')
{
cout << number << " * 2 * 3.14 = " << result << endl;
}
else if (choice == 'd') {
cout << number << " * 3.14 = " << result << endl;
}
else {
cout << "Nothing here cause you didn't do simple stuff correctly..." << endl;
}
return 0;
}
Since you are new couple things you need to remember:
switch case and if/else statement are pretty similar, therefore you don't need to use them both at the same time on same task.
When the program runs the user inputs a value either r or d , that value get passed to the choice variable. The switch case compares its own cases to the choice value and if both value are equal, it will run that case code block and if they are not it will run the default code.
Now inside the case, you are asking for the radius, once you get the radius,
result = number * number * M_PI;
OR
result = pow(number,2.0) * M_PI;
And also there is a big difference between cout<<"2*3"; and cout<<2*3;
The first example will display 2*3 into your screen.
The second example will display the result of 2*3 into the screen
6, the reason you it calculates because there is not quotation mark around it
Hope that helps...
Shoulr calculation of result use choise???
Looks like you have a typo. Replace choise woth number in the
result = choice*choice*M_PI;
And in the
result = choice*M_PI;
Using choise in calculation actually uses its ASCII code. This explains the big values that you get in the result.
result = choice*choice*M_PI;
this should be
result = number * number * M_PI;
also you are printing
* 2 * 3.14 =
should be
^ 2 * 3.14 =

Unknown issue when calculating bouyancy in C++

I'll cut to the chase: I made a program in C++ that calculates if a spherical object is bouyant or not for a class. However, after I (from what I thought) successfully made the program in Visual Studio 2013 when I submitted it where I need to (Pearon's terrible myProgrammingLab) I get the wrong output compared to Pearon's. (IE: Mine says it floats, they say it sinks, but don't show the calculations themselves.)
Here is my code:
// Bouyancy formula:
// Fb = V * y
// Where:
// Fb is the bouyant force
// V is the volume of the submerged object
// y is the specific weight of the fluid
// If Fb is greater than or equal to the weight of the object, then it will float, otherwise it will sink.
// Sphere volume formula:
// (4/3)pi(radius cubed)
#include "stdafx.h"
#include <iostream>
#define _USE_MATH_DEFINES // Used with math.h to provide access to M_PI (used in calculation of volume)
#include <math.h> // M_PI is the value of pie (3.14..)
using namespace std;
int main()
{
float sphere_radius, sphere_weight; // Stores the value of the Sphere's radius and weight in feet and pounds respectively.
double water_weight = 62.4; // Value set to 62.4lb /cubic feet, this value is the "y" value in the above formula.
double bouyant_force, volume; // Defines Fb and V in the Bouyancy formula listed above.
cout << "Enter the radius of the sphere, in feet: ";
cin >> sphere_radius;
cout << "\nEnter the weight of the sphere, in pounds: ";
cin >> sphere_weight;
cout << endl;
volume = ((4.0 / 3.0) * M_PI * (pow(sphere_radius, 3))); // Calculates the volume of the sphere
bouyant_force = (volume * water_weight);
if (bouyant_force >= sphere_weight)
{
cout << "The sphere will float." << endl;
}
else if (bouyant_force < sphere_weight)
{
cout << "The sphere will sink." << endl;
}
else { cout << "Something went terribly, terribly, wrong.. Oh dear.."; }
char x;
cin >> x; //Waits for user to press a key before closing the program.
return 0;
}
Can anyone please help me understand why this isn't correct or why it isn't being registered as correct? Thanks in advance!
Judging by your code, the error seems to be you directly comparing the weight you accept against the buoyant force. You should be multiplying the mass you accept(the pound is a unit of mass) by g in the unit system you are using. That seems to account for you getting that it flaots while the other side calculates that it sinks.

C++ How to check an input float variable for valid input

I'm writing a program that acts as a calculator; based on the character input by the user it performs a certain operation. The structure of the program seems to work fine, but I'd like to be able to check for erroneous input. After receiving the float variable, is there any way to check if it does not contain any characters other than digits and decimals? I've tried isdigit, and this:
if (!(cin >> x)) {
cout << "You did not enter a correct number!" << endl;
return;
}
But nothing seems to be working.
Here is a sample of one of the simple operation functions I'm using:
void Add(){
float x = 0, y = 0, z = 0;
cout << "Please enter two numbers you wish "
<< "to add separated by a white space:" << endl;
cin >> x >> y;
z = x+y;
cout << x << " + " << y << " = " << z << "." << endl;
return;
}
You test the state of the stream:
float x, y;
if (std::cin >> x >> y) {
// input extraction succeeded
}
else {
// input extraction failed
}
If this isn't working for you, then you need to post the exact code that isn't working.
To detect erroneous string input where you expected a number, C++ doesn't automatically know what you want, so one solution is to first accept your input as strings, validate those strings, then if valid, only then convert the strings to float numbers using the atof() function.
The standard string class has a function called find_first_not_of() to help you tell C++ which characters you consider valid. If the function finds a character not in your list, it will return the position of the bad character, otherwise string::npos is returned.
// add.cpp
#include <iostream>
#include <string>
#include <cstdlib> // for atof()
using namespace std;
void Add()
{
cout << "Please enter two numbers you wish "
<< "to add, separated by a white space:"
<< endl;
string num1, num2;
cin >> num1;
if( num1.find_first_not_of("1234567890.-") != string::npos )
{
cout << "invalid number: " << num1 << endl;
return;
}
cin >> num2;
if( num2.find_first_not_of("1234567890.-") != string::npos )
{
cout << "invalid number: " << num2 << endl;
return;
}
float x = 0, y = 0, z = 0;
x = atof( num1.c_str() );
y = atof( num2.c_str() );
z = x+y;
cout << x << " + " << y << " = " << z << "." << endl;
}
int main(void)
{
Add();
return 0;
}
One possibility would be to read the input as a string, then use boost lexical_cast to convert to floating point. lexical_cast only considers the conversion successful if the entire input converts to the target -- otherwise, it'll throw a bad_lexical_cast exception.
Another idea would be to test the input against a regex. An example regex for a float could be
-?[0-9]+([.][0-9]+)?
This method would also make it easier to refine the matching mechanism by only modifying the regex, and you could map multiple regular expressions against different types of input, for example an integer could then be expressed as
-?[0-9]+
and so on. Keep in mind however, that this only tests if the input is a valid format, it still requires a numerical conversion afterwards (I prefer boost::lexical_cast).
(You can also try it out with http://gskinner.com/RegExr/)