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);
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Aug 11, 2017 at 21:03
\$\endgroup\$

1 Answer 1

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;
}
answered Aug 12, 2017 at 17:28
\$\endgroup\$
1
  • \$\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\$ Commented Aug 12, 2017 at 18:24

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.