4
\$\begingroup\$

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);
}
\$\endgroup\$
6
\$\begingroup\$
  • 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;
}
\$\endgroup\$
  • \$\begingroup\$ 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 :/ \$\endgroup\$ – Distant Graphics Aug 12 '17 at 18:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.