# Temperature Conversion Program

I'm having trouble accessing variables throughout multiple functions. For example, I need to use userinput throughout many other functions, but do not have access to it with my current code. I am pretty sure that I need to change the parameters of my functions, so that I can pass the value of those functions by reference, but I'm having trouble doing that.

Here's what my code looks like right now:

#include <cstdlib>
#include <iostream>
#include <cmath>
#include <iomanip>

using namespace std;

double fahrtocels();
double celstofahr();
double celstokelv();
double kelvtocels();

int main()
{
do { int userinput=0;

cout << " 1) Fahr to Cels" << endl;
cout << " 2) Cels to Fahr" << endl;
cout << " 3) Cels to Kelv" << endl;
cout << " 4) Kelv to Cels" << endl;
cin >> userinput;
if(userinput=1)
fahrtocels();
if(userinput=2)
celstofahr();
if(userinput=3)
celstokelv();
if(userinput=4)
kelvtocels(); } while(userinput=0);

}

double fahrtocels()
{
int input;
int tempinput;
double finaloutput;
cout <<" Please Enter the Temp in Fahrenheit"<<endl;
cin >> input;
userinput= 1;
tempinput = input - 32;

finaloutput = tempinput/1.8;

cout<<input<< " degrees fahrenheit is equivalent to  " << finaloutput<< "  celsius"<< endl;
userinput = 0;
}

double celstofahr()
{
int inputcels;
int tempinputcels;
double finaloutputcels;
cout <<" Please Enter the Temp in Celsius"<<endl;
cin >> inputcels;

tempinputcels = inputcels * 1.8;

finaloutputcels = tempinputcels + 32;

cout<<inputcels<< " degrees celsius is equivalent to  " << finaloutputcels<< "  fahrenheit"<< endl;
}

double celstokelv()
{
int inputcelskelv;
double finaloutputcelskelv;
cout <<" Please Enter the Temp in Celsius for Kelvin Conversion"<<endl;
cin >> inputcelskelv;

finaloutputcelskelv = inputcelskelv + 273.15;

cout<<inputcelskelv<< " degrees celsius is equivalent to  " << finaloutputcelskelv<< " kelvin"<< endl;
}

double kelvtocels()
{
int inputkelvcels;
double finaloutputkelvcels;

cout <<" Please Enter the Temp in Kelvin for Celsius conversion"<<endl;
cin >> inputkelvcels;

finaloutputkelvcels = inputkelvcels - 273.15;

cout<<inputkelvcels<< " degrees kelvin is equivalent to  " << finaloutputkelvcels<< " celsius"<< endl;
}


First, the code is technically off-topic, since it has a pretty clear bug (in main):

} while(userinput=0);


This is almost certainly intended to be userinput==0. As-is, it's an assignment, which yields 0, which is treated as false, so the loop only ever executes once, regardless of input from the user.

While I agree with the basic approach @Konrad has advocated, putting together a table of the data needed for the conversions, I think I'd implement it just a bit differently. I would not use std::pair. I'd explicitly define a struct so the values would have meaningful names:

struct conversion {
double offset;
double coefficient;
};


Then your conversion would look like:

double convert(conversion_type conversion, double input) {
conversion c = conversions[conversion];
return (input+c.offset)*c.coefficient;
}


...which seems more readable, at least to me. If you do want to maintain separate functions for each conversion, I'd still break things up into one function doing input. another doing the conversion itself, and a third to display the result. I'd still make it largely table drive, using a vector (or array) of pointers to functions, using the number entered by the user to to index into that (after assuring that it's within range, of course).

• I agree that yours is cleaner. Mine is kind of like the Python approach in C++. I’d even think about inheritance to model this (have a base class taking care of the conversion and child classes to populate the offset & coeff in the constructor). That way, the classes can also take care of holding the scale’s names. Apr 19, 2012 at 13:09

Your problem is completely unrelated to smart pointers.

The keyword here is separation of concerns. You have a function (well, several of them) who try to do everything: create a prompt, control user input, convert a value, and output the result.

This is bad. You should separate these concerns rigorously.

At the heart of your program is a conversion function with the prototype

double convert(double input);


Of course, you have several of them – one for each unit-to-unit conversion (this can be done differently by first converting to a common unit but we’ll omit this for now).

Then you need an input and an output routine, which may look as follows:

double read_number(std::string const& unit) {
std::cout << "Please enter the temperature in " << unit << std::flush;
double value;
std::cin >> value;
return value;
}


and

void print_result(std::string const& from_unit, std::string const& to_unit, double from, double to) {
std::cout << from << " " << from_unit << " is equivalent to "
<< to << " " << to_unit << "\n";
}


The conversions are then straightforward one-liners, for instance:

double celsius_to_kelvin(double value) {
return value + 273.15;
}


(Furthermore, note that while it’s “degrees celsius”, it’s simply “kelvin” – not “degrees kelvin”.)

You could even use the same function for all conversions and merely store the scaling factor and offset. Such as:

typedef std::pair<double, double> coefficients_t;

std::vector<coefficients_t> conversions = {
{ 273.15, 1 }, // °C => K
{ -32, 0.5556 }, // °F => °C
…
};

enum conversion_type {
CtoK,
FtoC,
…
};

double convert(conversion_type conversion, double input) {
coefficients_t coef = conversions[conversion];
return (input + coeffs.first) * coeffs.second;
}


(This syntax requires C++11, C++03 is more verbose.)

if(userinput==1)
...
if(userinput=2)
...


consider to use either switch or else if constructions in such cases

if     (userinput==1)
...
else if(userinput==2)
...


also consider to play this trick

double(*)(void) fp[] = {fahrtocels, celstofahr, celstokelv, kelvtocels}
fp[userinput]() // calling function depends on the input number