# Converting between different units of temperature

The task is to convert a temperature in a list of Fahrenheit, Celsius, or Kelvin to the two other temperatures in the list.

Here is my code:

/*
* #define LANG C
*/

#include <stdio.h> /** standard io **/
#include <stdlib.h> /** exit(), atof and the lot **/
#include <unistd.h> /** needed for getopt() **/

/*** SYMBOIC CONSTANTS ***/
#define VERSION "1.0" /** version string array **/
#define HELP help(argv[0]) /** will insert this instead of help(argv[0]) every time **/
#define FLOATARG atof(optarg) /** atof is kind of vague, so a #define is better **/
#define TOVERH "FAHR\tCELSIUS\tKELVIN\n" /** just so I don't have to type it out ever time **/
#define OPTS "vk:f:c:h" /** I prefer a #define to this -> b:ull:s::hi:t: **/
/** For reference, an option followed by a double colon **/
/**        signifies that it takes no arguments         **/
/**  while an option followed by one colon signifies    **/
/**           that it takes one argument.               **/

static const char *ver = VERSION;

void help(char *s);

int check(float N) { /** check if kelvin temperature is celsius 0 **/
if(N > 273.1499 && N < 273.15001) { /** I had to set this limit. There is no other way. **/
return 1;
}
else {
return 0;
}
}

/*** Fahrenheit ***/
float FK(float F) {
return(((5.0 / 9.0) * (F - 32.0)) + 273.15);
}
float FC(float F) {
return((5.0 / 9.0) * (F - 32.0));
}
void printfahr(float F) {
printf(TOVERH);
printf("%4.3f\t%5.3f\t%5.3f\n", F, FC(F), FK(F));
}

/** Celsius **/
float CK(float C) {
return((C + 273.15));
}
float CF(float C) {
return((C * (9.0 / 5.0) - 32.0));
}
void printc(float C) {
printf(TOVERH);
printf("%4.3f\t%5.3f\t%5.3f\n", CF(C), C, CK(C));
}

/*** Kelvin ***/
float KC(float K) {
return(K - 273.15);
}
float KF(float K) {
return((K - 273.15) * (9.0 / 5.0) - 32.0);
}
void printk(float K) {
printf(TOVERH);
printf("%4.3f\t%5.3f\t%5.3f\n", KF(K), KC(K), K);
}

int main(int argc, char *argv[]) {
if(argc == 1) {
HELP;
exit(argc);
}
else {
char arg = '\0';
while((arg = getopt(argc, argv, OPTS)) != -1)
{
switch(arg) {
case 'c':
if(optarg == NULL)
{
HELP;
exit(1);
}
else {
printc(FLOATARG);
}
break;

case 'f':
if(optarg == NULL)
{
HELP;
exit(1);
}
else {
printfahr(FLOATARG);
}
break;

case 'h':
HELP;
break;

case 'k':
if(optarg == NULL)
{
HELP;
exit(1);
}
else {
if(check(FLOATARG) != 0)
{
printf(TOVERH);
printf("32.0\t0\t273.15\n");
}
else {
printk(FLOATARG);
}
}
break;

case 'v':
printf("%s\n", ver);
break;

default:
HELP;
break;
}
}
}
return 0;
}

void help(char *s) {
printf("Usage:\t%s [-c Celsius] [-f Fahrenheit] [-h] [-k Kelvin] [-v]\n", s);
}


• Numerical consts are double, either add them eg as 5.0f or use double.
• Define a constants for 0°C = 273.15K and also for Fahrenheit to Celsius conversation (avoid repeated magic constants 273.15, 9.0 / 5.0, 32.0).
• In check the distance from 273.15 is not symmetric, probably a typo.
• The name check doesn't imply what is checked, meaningful names not limited to this function would be a recommended.

A modified version could include:

#include <math.h>

const double Celsius2KelvinShift = 273.15;
const double Fahrenheit2KCelsiusShift = 32.0;
const double Fahrenheit2CelsiusFactor = 5.0 / 9.0;

/** check if kelvin temperature is celsius 0 **/
int checkIf0Celsius(double N)
{
const double tol = 0.001; /** I had to set this limit. There is no other way. **/
return fabs(N - Celsius2KelvinShift) < tol;
}

/*** Fahrenheit ***/
double Fahrenheit2Kelvin(double F)
{
return Fahrenheit2CelsiusFactor * (F - Fahrenheit2KCelsiusShift) + Celsius2KelvinShift;
}

double Fahrenheit2Celsius(double F)
{
return Fahrenheit2CelsiusFactor * (F - Fahrenheit2KCelsiusShift);
}

/** Celsius **/
double Celsius2Kelvin(double C)
{
return C + Celsius2KelvinShift;
}

double Celsius2Fahrenheit(double C)
{
return C / Fahrenheit2CelsiusFactor - Fahrenheit2KCelsiusShift;
}

/*** Kelvin ***/
double Kelvin2Celsius(double K)
{
return K - Celsius2KelvinShift;
}

double Kelvin2Fahrenheit(double K) {
return (K - Celsius2KelvinShift) / Fahrenheit2CelsiusFactor - Fahrenheit2KCelsiusShift;
}

• Good answer. As for the asymmetry, I set it because I wasn't sure how far to go; I saw that 273.15 as a float was in fact being stored as 273.1994 or something like that; I originally intended to ask on SO why this was the case, but... I got a 6-Month ban because too many people downvoted my questions there :/ Aug 12, 2017 at 18:24