Having a problem writing a class in C++; undeclared identifiers - c++

I am coding a class for the quadratic equation. I have been given the .h file, and have to write it based on that. I experience problems when I am trying to establish the "display" function, where I am getting undeclared identifier areas (as shown here):
'my_a' : undeclared identifier
'my_b' : undeclared identifier
'my_c' : undeclared identifier
'display' : function-style initializer appears to be a function definition
I would appreciate a little direction in my code. I am including the .h file at the bottom.
#include <iostream> // for cout, cin, istream, ostream
#include <cmath> // for floor
#include <string> // for class string
#include "quad.h"
using namespace std;
quadraticEquation::quadraticEquation (double initA,
double initB, double initC)
{
my_a = initA;
my_b = initB;
my_c = initC;
}
double quadraticEquation:: root1() const
{
double result = 0.0;
result= ((-1* my_b)+(sqrt((my_b*my_b)- (4*my_a*my_c)))/(2*my_a));
return result;
}
double quadraticEquation:: root2() const
{
double result = 0.0;
result= ((-1*my_b)- (sqrt((my_b*my_b)- (4*my_a*my_c)))/(2*my_a));
return result;
}
bool hasRealRoots(double root1 , double root2)
// post: returns true if an only if b*b-4*a*c >= 0.0, otherwise return false
{
bool result;
{
if (root1 >= 0.0) {
if (root2 >= 0.0){
result = true;
}
else
{
return false;}
}
}
}
void display (my_a, my_b, my_c)
// post: shows the quadratic equation like -1x^2 + 3x - 9.7
// when my_a == -1, my_b = 3, and my_c == -9.7
{
if (my_a >= 0)
cout <<my_a<< "x^2"<<;
else
cout <<"-"<< abs(my_a)<<"x^2"<<;
if(my_b >= 0)
cout << " + " << my_b << "x";
else
cout << " - " << abs(my_b) << "x";
if (my_c >= 0)
cout <<" + "<<my_c<< endl;
else
cout << " - "<<my_c<< endl;
return display;
}
And
#ifndef _QUAD_H
#define _QUAD_H
// file name: quad.h (the file on disk lists pre- and post-conditions)
class quadraticEquation {
public:
//--constructor (no default constructor for quadraticEquation)
quadraticEquation(double initA, double initB, double initC);
// post: initialize coefficients of quadratic equation initA*x*x + initB + c
//--accessors
double root1() const;
// pre: there is at least one real root: b*b-4*a*c >= 0.0
// post: returns one real root as (-b+sqrt(b*b-4*a*c)) / (2*a)
double root2() const;
// pre: there is at least one real root: b*b-4*a*c >= 0.0
// post: returns one real root as (-b-sqrt(b*b-4*a*c)) / (2*a)
bool hasRealRoots() const;
// post: returns true if an only if b*b-4*a*c >= 0.0, otherwise return false
void display() const;
// post: shows the quadratic equation like -1x^2 + 3x - 9.7
// when my_a == -1, my_b = 3, and my_c == -9.7
private:
double my_a, my_b, my_c; // the three coefficients of the quadratic equation
};
#endif

The header file shows display() taking no parameters. You've coded one that takes parameters, but you haven't included their types:
void display (my_a, my_b, my_c)
Start by making those brackets empty and things should get a lot better.
Second, display should be a member function of the class. That's how it will get access to my_a, my_b, and my_c.
void quadraticEquation::display()
Third, hasRealRoots should also be a member function of the class, taking no parameters - and your code should not just see if both numbers are positive (which makes no sense) but actually evaluate the b^2-4ac term and see if it's positive (meaning the roots of the equation will be real rather than complex.)

the use of your display function is wrong(in cpp file). just use it as
void display()
since it doesnt need params and all the params it needs are already initialised.
missed a point..
write it as void quadraticEquation::display() rather than void display()

void quadraticEquation::display (double my_a, double my_b, double my_c)
// post: shows the quadratic equation like -1x^2 + 3x - 9.7
// when my_a == -1, my_b = 3, and my_c == -9.7
{
if (my_a >= 0)
cout <<my_a<< "x^2"<<;
else
cout <<"-"<< abs(my_a)<<"x^2"<<;
if(my_b >= 0)
cout << " + " << my_b << "x";
else
cout << " - " << abs(my_b) << "x";
if (my_c >= 0)
cout <<" + "<<my_c<< endl;
else
cout << " - "<<my_c<< endl;
return display;
}

Related

CPP: why is dereferencing a pointer to a template type not populating a variable?

I do a lot of modeling and simulation and I am writing a sim_logger in CPP. The basics of it are this: a user constructs the class with a logging frequency and an output path. They can then "register" any number of variables which gives the logger a reference to the desired variable (its not incredibly safe right now but I'll work on that later, focused on the issue at hand). I've created a template type called "variable" which contains three things, T *var, T last_val, and string ID. My problem is this, whenever I set the last_val equivalent to the var, the last_val inside the variable does not actually change. I am setting this value in line 180 of sim_logger.h. I feel like this is a silly problem, probably due to some misunderstanding I have of pointers. However, I've tried several different things and cannot seem to solve this problem.
sim_logger.h
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <variant>
#include <type_traits>
#include <math.h>
pragma once
// a class to log simulation data
// specifically for logging time dependent differential functions
class sim_logger
{
private:
// a type that represents a variable
/*
meant to contain anything, but limited by the variadic type
"poly_var_types" below
*/
template <typename T>
struct variable
{
T *var; // pointer to the variable itself
T last_val; // the last value of the variable
std::string ident; // the identity of the variable
};
// a variadic type
template <typename ... T>
using poly_var_types = std::variant<T...>;
// defined variable types
// these are the typical types that are logged, feel free to add more
using var_types = poly_var_types<
variable<double>,
variable<float>
// variable<int>,
// variable<bool>,
// variable<std::string>
>;
// class members
std::vector<var_types> registered_variables; // container of all variables
std::ofstream file; // output file stream
double dt; // the logging time step in seconds
double clock = 0.0; // the logging clock in seconds
double last_sim_time = clock; // the last sim time for interp
bool is_time_to_log = false; // flag for log function
const double EPSILON = 0.000000001; // rounding error
// a linear interpolation method
// only returns floating point values
double lin_interp(double x, double x1, double x2, double y1, double y2)
{
return (y1+(x-x1)*((y2-y1)/(x2-x1)));
}
public:
// constructor which sets the logging frequency and output path
// log_dt is a floating point value in units of seconds
// path_to_file is a string representation of the desired output path
sim_logger(double log_dt, std::string path_to_file)
{
dt = log_dt;
file.open(path_to_file);
file << std::setprecision(16) << std::fixed;
}
// method to register a variable with the logger
template <typename T>
void register_variable(std::string ident, T *aVar)
{
variable<T> v;
v.ident = ident;
v.var = aVar;
registered_variables.push_back(v);
};
// a method to write the log file header and log sim time 0.0 data
void write_header_and_log_init_data()
{
// write header
file << "sim_time" << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << rv.ident << "\n";
else
file << rv.ident << " ";
}, registered_variables[i]);
}
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << *rv.var << "\n";
else
file << *rv.var << " ";
}, registered_variables[i]);
}
}
// method to log all registered variables
void log_data(double sim_time)
{
// check the timing
if (sim_time > (clock + dt))
{
is_time_to_log = true;
}
// check if its time to log
if (is_time_to_log)
{
// update the clock
clock += dt;
// debug
std::cout << "\n";
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// instantiate the value to be logged
double log_val;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
// if sim time is even with clock time, log at time
if (fabs(sim_time - clock) < EPSILON)
// if (true)
{
log_val = *rv.var;
}
// if sim time is past clock time, interpolate
else
{
log_val = lin_interp(sim_time, last_sim_time,
clock, rv.last_val, *rv.var);
}
// if last variable in vector create new line
if (i == registered_variables.size()-1)
file << log_val << "\n";
// otherwise just whitespace
else
file << log_val << " ";
}, registered_variables[i]);
}
// debug
std::cout << "\n";
// reset flag
is_time_to_log = false;
}
// get all the last values
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// have to get last value at every update call
// This works in scope but the memory does not actually change?
// I am very confuse.
rv.last_val = *rv.var;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
}, registered_variables[i]);
}
// set the last sim time
last_sim_time = sim_time;
}
};
main.cpp
include <iostream>
include "sim_logger.h"
int main()
{
sim_logger logger(0.1, "sim_logger/log.dat");
double test1 = 100.0;
double test2 = 100.0;
double test3 = 100.0;
logger.register_variable("test1", &test1);
logger.register_variable("test2", &test2);
logger.register_variable("test3", &test3);
logger.write_header_and_log_init_data();
double simTime = 0.0;
double simDt = 1.0 / 20.0;
for (int i = 0; i < 3; i++)
{
simTime += simDt;
test1 += 1.0;
test2 += 2.0;
test3 += 3.0;
logger.log_data(simTime);
}
return 0;
};
output
101 101
102 102
103 103
102 102
104 104
106 106
1.88705e-26 103
1.88705e-26 106
1.88705e-26 109
103 103
106 106
109 109
std::visit([&](auto rv)
rv is, effectively, a parameter to this function (the closure, for the purposes of this answer, is effectively a function).
As you know: in C++ function parameters get passed by value. For example, using a simple function:
void func(int x)
{
x=5;
}
This func can set x to 5 as often as it wants. Whatever actually gets passed in, by anyone that calls func(), will remain unaffected:
int z=7;
func(z);
z is still 7. Even though func set its parameter to 5. This is fundamental to C++:
std::visit([&](auto rv)
{
rv.last_val = *rv.var;
So, this sets rv.last_val. Great. But this has no effect on whatever gets passed into here.
}, registered_variables[i]);
The visited instance of this variant is still what it is. It hasn't changed. Why would it change? C++ does not work this way.
So, if your intent, here, is to modify registered_variables[i], it should be passed by reference:
std::visit([&](auto &rv)
Now, the object referenced by rv gets modified.

Cannot modify the private value in member function of the class

I am wondering what is going on in my app.
The problem is that I cannot modify one of my private values (temperature) from the class Room while the other private one (targetTemp) changes without any problems.
I've got a function setTargetTemp where I can assign the value for targetTemp - works (Room.cpp line 18-20).
I've got another function outsideImpact where I can assign the value for temperature - doesn't work (Room.cpp line 21-27). The method is the same (excluding some calculations).
In main.cpp I called both functions (line 15 and 16) in a loop. While debugging I can see that livingRoom's temperature remains the same at every iteration, targetTemp on the other hand is changing as expected.
So what is the difference? What am I missing here?
Room.h
class Room {
private:
float
temperature, // Temperature in the room
targetTemp, // Target temperature in the room
factor; // Susceptibility of the room to cooling/heating - 1 is default, +- 0.25 = ~ 1.5 C-deg / >1 - faster
public:
Room(void);
~Room(void);
float getTemp(void);
float getTargetTemp(void);
void setTargetTemp(float target);
void outsideImpact(float outsideTemp);
};
Room.cpp
#include "./Room.h"
#include <iostream>
#include <cmath>
Room::Room(void) {
temperature = 15.;
targetTemp = 22.;
factor = 1;
}
Room::~Room(void) {}
float Room::getTemp(void) {
return temperature;
}
float Room::getTargetTemp(void) {
return targetTemp;
}
void Room::setTargetTemp(float target) {
targetTemp = target;
}
void Room::outsideImpact(float outsideTemp) {
float trendValue = (abs(temperature - outsideTemp) / 100 * factor);
if(temperature > outsideTemp)
temperature -= trendValue;
else
temperature += trendValue;
}
main.cpp
#include "./Room.h"
#include <iostream>
#include <cmath>
using namespace std;
int main(void){
float
timer = 0.,
outsideTemp = -10.;
Room livingRoom;
do {
timer += 0.25;
livingRoom.outsideImpact(outsideTemp); // change the "temperature"
livingRoom.setTargetTemp(26.+timer); // change the "targetTemp"
cout << "Living room temp: " << livingRoom.getTemp() << " || Outside temp: " << outsideTemp
<< " || Time: " << timer << " hour(s)" << "\t|| TARGET: " << livingRoom.getTargetTemp() << endl;
} while (round(livingRoom.getTemp()) != round(outsideTemp));
return 0;
}

How do Boost.Geometry operations like union_ deal with the fundamental imprecision of floating point types?

I'm trying to judge whether / how I can make Boost.Geometry work for a particular use case. I cannot, however, find documentation about how the library deals with floating point types anywhere.
If you search the official documentation for the word "epsilon" you get zero hits as far as I can tell; however, it is clear from the library's behavior that it is implicitly using some version of the typical way one deals with floats when making comparisons because, for example, the union_ operation will union two polygons that are near each other but not overlapping if they are near enough.
Consider for example the following code which performs a binary search to determine the threshold distance that two unit squares need to be within to be considered adjacent when union-ing:
namespace bg = boost::geometry;
using point = bg::model::d2::point_xy<double>;
using polygon = bg::model::polygon<point, false>;
polygon create_poly(std::vector<std::tuple<double, double>> pts) {
polygon poly;
for (const auto& [x, y] : pts)
bg::append(poly, bg::make<point>(x, y));
auto [x_1, y_1] = pts[0];
bg::append(poly, bg::make<point>(x_1, y_1));
return poly;
}
bool perform_simple_union(const polygon& p1, const polygon& p2) {
std::vector<polygon> output;
bg::union_(p1, p2, output);
return output.size() == 1;
}
double find_epsilon(double left, double right) {
if (right - left < std::numeric_limits<double>::epsilon())
return left;
double eps = (left + right) / 2;
polygon a = create_poly(
std::vector<std::tuple<double, double>>{
{1.0, 1.0}, { 2.0,1.0 }, { 2.0, 2.0 }, { 1.0,2.0 }
}
);
polygon b = create_poly(
std::vector<std::tuple<double, double>>{
{2.0 + eps, 1.0}, { 3.0 + eps, 1.0 }, { 3.0 + eps, 2.0 }, { 2.0 + eps,2.0 }
}
);
if ( perform_simple_union(a, b) ) {
return find_epsilon(eps, right);
} else {
return find_epsilon(left, eps);
}
}
int main()
{
auto eps = find_epsilon(0.0, 1.0);
std::cout << "eps == " << eps << "\n";
}
when I compile and run the above with Visual Studio I get the output
eps == 1e-07
which is about the numeric limits epsilon of single precision floats. So it's treating double precision coordinates as if they are equivalent if they are within single precision epsilon from each other?
Basically I'd just like to know what the default behavior is so I can decide if it works for me.
In [the intro][1], it states:
The library supports high precision arithmetic numbers, such as ttmath.
[1]: https://www.boost.org/doc/libs/1_70_0/libs/geometry/doc/html/geometry/introduction.html
The library design rationale goes into this a tiny bit more:
[...], it would be too long, and it is not related to geometry. We just assume that there is a meta-function select_most_precise selecting the best type.
They also implemented along the OGC Simple Feature Specification, which probably means that you can find more algorithmic robustness guarantees there.
I know from reading the code that there are certain algorithms that take into account edge cases where the outcome can be made more robust (by doing operations in a certain order or noticing when features are very close, IIRC). A simple grep for e.g. robust might show you some in-roads there:
policies/robustness/robust_point_type.hpp:// Meta-function to typedef a robust point type for a poli
algorithms/detail/overlay/get_turn_info_helpers.hpp: // Used ranges - owned by get_turns or (for
algorithms/detail/overlay/get_turn_info_helpers.hpp:// Version with rescaling, having robust points
algorithms/detail/overlay/append_no_dups_or_spikes.hpp: // Try using specified robust policy
I'm merely grazing the surface here, I don't claim to understand much of what is being noted there.
Using arbitrary precision or decimals
Precision is one dimension, source-fidelity when the input is in decimal form is another. Short of going to MPFR/GMP/ttmath (as mentioned) you can easily drop in Boost Multiprecision. This gives you fast proof-of-concept since it ships with boost, and also allows you to switch to GMP or MPFR backends transparently.
See also:
Boost Geometry and exact point types
How to use Boost::Geometry _union with integers
Boost geometry intersection does not output correctly
Live On Coliru
#include <boost/geometry.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <iostream>
namespace mp = boost::multiprecision;
namespace bg = boost::geometry;
//// Note, cpp_dec_float<0> is variable-precision!
// using Number = mp::number<mp::cpp_dec_float<0>, mp::et_off>;
// Fixed precision, avoids allocating and populates std::numeric_limits<>
// with concrete data
using Number = mp::number<mp::cpp_dec_float<50>, mp::et_off>;
using point = boost::geometry::model::d2::point_xy<Number>;
using polygon = bg::model::polygon<point, false>;
polygon create_poly(std::vector<std::tuple<Number, Number>> pts) {
polygon poly;
for (const auto& [x, y] : pts)
bg::append(poly, bg::make<point>(x, y));
auto [x_1, y_1] = pts[0];
bg::append(poly, bg::make<point>(x_1, y_1));
return poly;
}
bool perform_simple_union(const polygon& p1, const polygon& p2) {
std::vector<polygon> output;
bg::union_(p1, p2, output);
return output.size() == 1;
}
Number find_epsilon(Number left, Number right) {
Number eps = (left + right) / 2;
if (right - left < std::numeric_limits<Number>::epsilon())
return left;
polygon a = create_poly(
std::vector<std::tuple<Number, Number>>{
{1.0, 1.0}, { 2.0,1.0 }, { 2.0, 2.0 }, { 1.0,2.0 }
}
);
polygon b = create_poly(
std::vector<std::tuple<Number, Number>>{
{2.0 + eps, 1.0}, { 3.0 + eps, 1.0 }, { 3.0 + eps, 2.0 }, { 2.0 + eps,2.0 }
}
);
if ( perform_simple_union(a, b) ) {
return find_epsilon(eps, right);
} else {
return find_epsilon(left, eps);
}
}
int main()
{
std::cout << "nextafter(0, 1): " << nextafter(Number(0), Number(1)) << "\n";
std::cout << "Number: eps() " << std::numeric_limits<Number>::epsilon() << "\n";
std::cout << "Number: min_exp() " << std::numeric_limits<Number>::min_exponent10 << "\n";
std::cout << "Number: max_exp() " << std::numeric_limits<Number>::max_exponent10 << "\n";
std::cout << "Number: min() " << std::numeric_limits<Number>::min() << "\n";
std::cout << "Number: max() " << std::numeric_limits<Number>::max() << "\n";
auto eps = find_epsilon(0.0, 1.0);
std::cout << std::setprecision(180);
std::cout << "eps == " << eps << "\n";
std::cout << std::boolalpha;
std::cout << "zero? " << (eps == 0) << "\n";
}
Prints
nextafter(0, 1): 1e-67108864
Number: eps() 1e-49
Number: min_exp() -67108864
Number: max_exp() 67108864
Number: min() 1e-67108864
Number: max() 1e+67108864
eps == 0
zero? true
For cpp_dec_float<0> it prints (note the "weird" numeric_limits<>::eps` in the variable-precision situation):
Live On Coliru
nextafter(0, 1): 1e-67108864
Number: eps() 1e-08
Number: min_exp() -67108864
Number: max_exp() 67108864
Number: min() 1e-67108864
Number: max() 1e+67108864
eps == 0
zero? true

C++: bool method returning unexpected numbers after cout statement

I'm working on some exam-examples for a c++ programming exam and the example where I'm stuck at requires me to code a class for returning the contents of a "Closet" object. One of the methods required in the example adds a vector of Garment objects to a second vector of Garment objects, (so, filling the closet with clothes). Up until this point my code has passed all the references and checks I've been given (a list with the supposed runtime errors and cout/cerr statements), so I've removed method-definitions and calls in the code I'm posting here to only show the part where I'm getting the unexpected returns.
I supposed that one of the constructors or even another method might interfere with the output, so I've ran several versions of the code trough a visualizer (Python tutor for c++), but that didn't shed any new insight either, no other methods were called (as expected) and no other output prompted from the constructors either.
#include <iostream>
#include <stdexcept>
#include <vector>
#include <string>
using namespace std;
enum class Color{Red, Blue, Gray, Yellow};
const std::vector<std::string> color_names{"red", "blue", "gray", "yellow"};
enum class Type{Pants, Blouse, Shirt, Skirt};
const std::vector<std::string> type_names{"pants", "blouse", "shirt", "skirt"};
class Garment {
int preis;
Color farbe;
Type typ;
public:
//Konstruktor
Garment (int p, Color f = Color::Gray, Type t = Type::Pants){
this->preis = p;
this->farbe = f;
this->typ = t;
//negativer Preis = exception
if (p < 0){throw runtime_error("Preis kleiner als 0!");} }
int get_price() const{
return this->preis; }
Type get_type() const{
return this->typ; }
bool has_color(Color f) const{}
void deteriorate(int w){}
int get_index_color() const{}
int get_index_type() const{}
friend ostream& operator<<(ostream& out, const Garment &g){
//[40000 Cent, yellow blouse]
out << "[" << g.preis << " Cent, "<< color_names[g.get_index_color()]
<< " " << type_names[g.get_index_type()];
out << "]";
return out;
}
};
class Closet {
size_t capacity;
vector<Garment> inventory;
public:
//Konstruktor Beginn
Closet (size_t c, vector<Garment> inv){
this->capacity = c;
this->inventory = inv;
if (capacity < 5 || capacity > 300){throw runtime_error ("Komplette Kapazitaet ueber oder unterschritten!");}
if (this->inventory.size() > this->capacity){throw runtime_error ("Relative kapazitaet ueberschritten");}
vector<int>kleiderliste {0,0,0,0};
for (auto x : inv){
if (x.Garment::get_type() == Type::Pants){kleiderliste[0]++;}
if (x.Garment::get_type() == Type::Blouse){kleiderliste[1]++;}
if (x.Garment::get_type() == Type::Skirt){kleiderliste[2]++;}
if (x.Garment::get_type() == Type::Shirt){kleiderliste[3]++;}
}
int zaehler = 0;
for (auto y : kleiderliste){
if (y != 0 ){zaehler++;}
}
if (zaehler <2){throw runtime_error("Nur mehr kleidungsstuecke eines typs im schrank");}
}
bool add(vector<Garment> v){
if ((v.size() + this->inventory.size()) <= this->capacity){
cerr << 1;
this->inventory.insert(this->inventory.begin(),v.begin(),v.end());
return true;
}else{
cerr << 0;
return false;
}
}
double mean_price() const{
}
friend ostream & operator<<(ostream &out,const Closet &c){
out << "[" << c.capacity << ",{";
for (auto x : c.inventory){
out <<x;
}
out << "},";
out << c.mean_price();
out << "]";
return out;
}
};
int main(){
Garment pants{34500, Color::Blue, Type::Pants};
Garment blouse{12700, Color::Red, Type::Blouse};
const Garment shirt{2300, Color::Yellow, Type::Shirt};
Garment shirt2{23500, Color::Red, Type::Shirt};
Garment skirt{26600, Color::Gray, Type::Skirt};
Garment skirt2{4600, Color::Blue, Type::Skirt};
Closet closet {10, {skirt, blouse, shirt, pants, skirt}};
cout << closet.add({shirt2, skirt2}) << closet.add({blouse,skirt,pants}) << closet.add({}) << closet.add({pants}) << '\n';
return 0; }
This code is supposed to yield the following output via cout:
1110. The Closet::add method is supposed to return true three times and false one time in a row.
What I actually get as return values via cout << is: 0111
To test if the code does what it's supposed to I'm outputting 1 for true and 0 for false on the cerr channel too, and there I get the correct 1110 numbers.
What leads to the return output not be 1110? Are the method calls made in a different order in the compiler?
As explained by Raymond-Chen the method is not guaranteed to be called in the left to right order that would produce the expected "1110" output. Different compilers lead to different order of the calls being executed. In this specific case switching to the clang compiler yielded the expected "1110" output.

Condensing functions to go two ways in C++

Apparently, I should be able to condense these six functions into three simpler functions that go two ways, using bool logic, but I have no idea where to start!
void footToMeter(int inputfeet) {
double outputMeter = ((inputfeet) / (3.281));
cout << outputMeter;
}
void meterToFoot(int inputmeter) {
double outputFoot = ((inputmeter)*(3.281));
cout << outputFoot;
}
void CtoF(int inputC) {
double outputF = 32 + (inputC*(9.0 / 5.0));
cout << outputF;
}
void FtoC(int inputF) {
double outputC = (5.0 / 9)*(inputF - 32);
cout << outputC;
}
void cMtocF(int inputcM) {
double outputcF = ((inputcM)*(35.315));
cout << outputcF;
}
void cFtocM(int inputcF) {
double outputcM = ((inputcF) / (35.315));
cout << outputcM;
}
One approach would be to add an extra parameter for each function to determine which direction you want to convert.
Example:
void lengthConversion(int inputLength, bool toFeet)
{
double output;
if (toFeet)
output = inputLength * 3.281;
else
output = inputLength / 3.281
cout << output;
}
#forthe has a point though - enum would make it a bit nicer.
To make it into 3 simpler functions. First try and bundle up the similarities between the current functions:
// Put the foot to meter and meter to foot functions into one, with 2 extra boolean values.
void fAndMConversion(int measurement , bool footToMeter , bool meterToFoot) {
if(footToMeter){
double fTm = ((measurement) / (3.281));
cout << fTm;
}
if(meterToFoot){
double mTf = ((measurement)*(3.281));
cout << mTf;
}
}
These are the first two functions. This also allows us to get foot to meter and meter to foot conversion in one call to the function: fAndMConversion(11 , true , true). You can bundle it up even further into a conversions() function with 7 args in total, 6 being booleans.