An introduction to Ch: Implementing a temperature converter in Ch

Ch is a combined C shell and IDE

Also, the program needs to include the file stdlib.h (#include <stdlib.h>), which includes a description of the exit function. With these changes, the complete program looks like the following:

#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <stdio.h>

enum {
SCALE_F = 1, /* constant value for Fahrenheit */
SCALE_C = 2 /* constant value for Celsius */
};

int which_scale(string_t scale) {

	/* return SCALE_F if the temperature scale is Fahrenheit or
F; use strcasecmp for case insensitive comparisons */

	if (strcasecmp(scale, "Fahrenheit") == 0 ||
strcasecmp(scale, "F") == 0) {
return SCALE_F;
}

	/* return SCALE_C if the temperature scale is Celsius or
C; use strcasecmp for case insensitive comparisons */

	if (strcasecmp(scale, "Celsius") == 0 ||
strcasecmp(scale, "C") == 0) {
return SCALE_C;
}

	return -1;
}

int main (int argc, string_t argv[]) {
string_t temp_raw, scale_in_raw, scale_out_raw;
int scale_in = -1, scale_out = -1;
float temp_in = 0.0;

	if (argc < 4) {
printf("Please specify the temperature and scales.\n");
exit(1);
}

	temp_raw = argv[1];
scale_in_raw = argv[2];
scale_out_raw = argv[3];

	/* check if the specified input temperature contained a
valid number */

	if (sscanf(temp_raw, "%f", &temp_in) != 1) {
printf("Invalid input temperature: '%s' degrees\n",
temp_raw);
exit(1);
}

	printf("Input temperature: '%f' degrees\n", temp_in);

	/* verify that the input temperature scale was either
Fahrenheit or Celsius */

	scale_in = which_scale(scale_in_raw);
if (scale_in != SCALE_F && scale_in != SCALE_C) {
printf("Invalid input temperature scale: '%s'\n",
scale_in_raw);
exit(1);
}

	printf("Input temperature scale: '%s'\n",
scale_in_raw);

	scale_out = which_scale(scale_out_raw);
if (scale_out != SCALE_F && scale_out != SCALE_C) {
printf("Invalid output temperature scale: '%s'\n",
scale_out_raw);
exit(1);
}

	/* verify that the output temperature scale was either
Fahrenheit or Celsius */

	printf("Output temperature scale: '%s'\n",
scale_out_raw);

	if (scale_in == scale_out) {
printf("Input and output scales are the same\n");
exit(1);
}

	exit(0);
}

Now when the program is executed with an invalid temperature, it displays the following output:

/> ch ./temp_converter.ch hello F C
Invalid input temperature: 'hello' degrees

When the program is executed with an invalid input temperature scale, it displays the following output:

/> ch ./temp_converter.ch 212 hello F
Input temperature: '212.000000' degrees
Invalid input temperature scale: 'hello'

Likewise, when the output temperature scale in invalid, the program displays the following output:

/> ch ./temp_converter.ch 212 F hello
Input temperature: '212.000000' degrees
Input temperature scale: 'F'
Invalid output temperature scale: 'hello'

When the input and output temperature scales are the same, the program displays the following output:

/> ch ./temp_converter.ch 212 F F
Input temperature: '212.000000' degrees
Input temperature scale: 'F'
Output temperature scale: 'F'
Input and output scales are the same

When the inputs are all valid, however, the program displays the following output:

/> ch ./temp_converter.ch 212 F C
Input temperature: '212.000000' degrees
Input temperature scale: 'F'
Output temperature scale: 'C'

Converting Temperatures

Now that the program is able to validate its inputs, it is finally possible to implement the actual process of converting from one temperature scale to another. This can be done by creating a pair of functions: one for converting Celsius temperatures to Fahrenheit temperatures, and another for converting Celsius temperatures to Fahrenheit temperatures.

To convert a Celsius temperature to a Fahrenheit temperature, the Celsius temperature is multiplied by 1.8 and 32 is added to the result: (1.8 × °C) + 32 = °F. The following function can be used to perform this calculation:

float celsius_to_fahrenheit(float c_temp) {
float f_temp = 0.0;
f_temp = (1.8 * c_temp) + 32;
return f_temp;
}

This function takes as its input a floating point value as containing a Celsius temperature (float c_temp) returns a floating point value (float) corresponding to the equivalent Fahrenheit temperature. First, this function creates and initializes a floating point variable, f_temp, to hold the Fahrenheit temperature (float f_temp = 0.0). Next, the function uses the multiplication operator (*) to multiply the input Celsius temperature, c_temp, by 1.8 and adds 32 to the result ((1.8 * c_temp) + 32). The parenthesis, (), surrounding 1.8 * c_temp ensures that this calculation will be performed first and then 32 will be added to the result. The result of the entire calculation is then assigned to f_temp (f_temp = (1.8 * c_temp) + 32) and this value is returned (return f_temp).

Similarly, to convert a Fahrenheit temperature to a Celsius temperature, 32 is subtracted from the Fahrenheit temperature and the result is divided by 1.8: (°F – 32) ÷ 1.8 = °C. The following function can be used to perform this calculation:

float fahrenheit_to_celsius(float f_temp) {
float c_temp = 0.0;
c_temp = (f_temp - 32) / 1.8;
return c_temp;
}

This function takes as its input a floating point value as containing a Fahrenheit temperature (float f_temp) returns a floating point value (float) corresponding to the equivalent Celsius temperature. First, this function creates and initializes a floating point variable, c_temp, to hold the Celsius temperature (float c_temp = 0.0). Next, the function subtracts 32 from the input Fahrenheit temperature, f_temp, and then uses the divide operator (/) divides the result ((f_temp - 32) / 1.8). The parenthesis, (), surrounding f_temp - 32 ensures that this calculation will be performed first and then the result will be divided by 1.8. The result of the entire calculation is then assigned to c_temp (c_temp = (f_temp - 32) / 1.8) and this value is returned (return c_temp).

To make use of these two functions the main function needs to be updated to use them as appropriate. The program should use the celsius_to_fahrenheit function when the input temperature scale was specified as Celsius and the output temperature scale was specified as Fahrenheit. This can be checked for using the following if statement:

if (scale_in == SCALE_C && scale_out == SCALE_F) {
temp_out = celsius_to_fahrenheit(temp_in);
printf("%f degrees C is %f degrees F" ,
temp_in, temp_out);
exit(0);
}

Here, the program checks whether the input temperature scale equals the constant value corresponding with the Celsius scale (scale_in == SCALE_C) and whether the output temperature scale, scale_out, equals the constant value corresponding with the Fahrenheit scale (scale_out == SCALE_F). If both of these are true, the program executes the celsius_to_fahrenheit function with the supplied temperature value (temp_in) and assigns the resulting value to the variable temp_out (which of course must be created and initialized at the beginning of the main function). A printf statement is used to print out the result, and then the program exits with an exit code of 0 (exit(0)), indicating that the program executed without encountering any problems.

Likewise, the following if statement determines whether input temperature scale was specified as Fahrenheit and the output temperature scale was specified as Celsius, and executes the fahrenheit_to_celsius function to do the conversion:

if (scale_in == SCALE_F && scale_out == SCALE_C) {
temp_out = fahrenheit_to_celsius(temp_in);
printf("%f degrees F is %f degrees C",
temp_in, temp_out);
exit(0);
}

Here, the program checks whether the input temperature scale equals the constant value corresponding with the Fahrenheit scale (scale_in == SCALE_F) and whether the output temperature scale, scale_out, equals the constant value corresponding with the Celsius scale (scale_out == SCALE_C). If both of these are true, the program executes the Fahrenheit_to_celsius function with the supplied temperature value (temp_in) and assigns the resulting value to the variable temp_out. A printf statement is used to print out the result, and then the program exits with an exit code of 0 (exit(0)), indicating that the program executed without encountering any problems.

Since the program does not allow the input and output temperature scales to be the same, the program should exit after executing one of these two if statements. If, however, some error occurs and the program continues executing, the program should exit with an exit code of 1 to indicate that an unexpected error occurred (exit(1)). In addition, the printf statements that display the input temperature, and input and output temperature scales are not needed any more, so they can be eliminated. With these changes, the complete program looks like the following:

#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <stdio.h>

int which_scale(string_t scale);
float celsius_to_fahrenheit(float c_temp);
float fahrenheit_to_celsius(float f_temp);

enum {
SCALE_F = 1, /* constant value for Fahrenheit */
SCALE_C = 2 /* constant value for Celsius */
};

float celsius_to_fahrenheit(float c_temp) {
float f_temp = 0.0;
f_temp = (1.8 * c_temp) + 32;
return f_temp;
}

float fahrenheit_to_celsius(float f_temp) {
float c_temp = 0.0;
c_temp = (f_temp - 32) / 1.8;
return c_temp;
}

int which_scale(string_t scale) {

	/* return SCALE_F if the temperature scale is Fahrenheit or
F; use strcasecmp for case insensitive comparisons */

	if (strcasecmp(scale, "Fahrenheit") == 0 ||
strcasecmp(scale, "F") == 0) {
return SCALE_F;
}

	/* return SCALE_C if the temperature scale is Celsius or
C; use strcasecmp for case insensitive comparisons */

	if (strcasecmp(scale, "Celsius") == 0 ||
strcasecmp(scale, "C") == 0) {
return SCALE_C;
}

	return -1;
}

int main (int argc, string_t argv[]) {
string_t temp_raw, scale_in_raw, scale_out_raw;
int scale_in = -1, scale_out = -1;
float temp_in = 0.0, temp_out = 0.0;

	if (argc < 4) {
printf("Please specify the temperature and scales.\n");
exit(1);
}

	temp_raw = argv[1];
scale_in_raw = argv[2];
scale_out_raw = argv[3];

	/* check if the specified input temperature contained a
valid number */

	if (sscanf(temp_raw, "%f", &temp_in) != 1) {
printf("Invalid input temperature: '%s' degrees\n",
temp_raw);
exit(1);
}

	/* verify that the input temperature scale was either
Fahrenheit or Celsius */

	scale_in = which_scale(scale_in_raw);
if (scale_in != SCALE_F && scale_in != SCALE_C) {
printf("Invalid input temperature scale: '%s'\n",
scale_in_raw);
exit(1);
}

	/* verify that the output temperature scale was either
Fahrenheit or Celsius */

	scale_out = which_scale(scale_out_raw);
if (scale_out != SCALE_F && scale_out != SCALE_C) {
printf("Invalid output temperature scale: '%s'\n",
scale_out_raw);
exit(1);
}

	/* no point in converting values, if the input and
output scales are the same */

	if (scale_in == scale_out) {
printf("Input and output scales are the same\n");
exit(1);
}

	/* if the input scale is Celsius and the output scale
is Fahrenheit, use the celsius_to_fahrenheit function

	if (scale_in == SCALE_C && scale_out == SCALE_F) {
temp_out = celsius_to_fahrenheit(temp_in);
printf("%f degrees C is %f degrees F\n",
temp_in, temp_out);
exit(0);
}

	/* if the input scale is Fahrenheit and the output scale
is Celsius, use the Fahrenheit_to_celsius function
to convert the temperature */

	if (scale_in == SCALE_F && scale_out == SCALE_C) {
temp_out = fahrenheit_to_celsius(temp_in);
printf("%f degrees F is %f degrees C\n",
temp_in, temp_out);
exit(0);
}

	exit(1);
}

Now, the program now correctly converts between Fahrenheit and Celsius:

/> ch ./temp_converter.ch 212 F C
212.000000 degrees F is 100.000000 degrees C
/> ch ./temp_converter.ch 0 C F
0.000000 degrees C is 32.000000 degrees F

Improvements

There are several minor improvements that could be made to this program to make it more useful. For example, the output, while correct, may be a little hard to read because of the number of decimal places that are displayed after the input and output temperatures. The output can be made slightly easier to read by limiting the number of decimal places displayed by changing the format specifier used by the printf statements. For values printed with a decimal point, such as those printed by the %l format specifier, the minimum length of the number to be printed and the number of decimal places to display can be change as follows:

%length.accuracyl

Here, length is the minimum length of the number, while accuracy is the number of decimal places to print out (to specify no minimum length for the number, a value of 0 can be used). For example, to limit the output to just 2 decimal places, the value of %0.2l can be used:

printf("%0.2f degrees C is %0.2f degrees F\n",
temp_in, temp_out);
printf("%0.2f degrees F is %0.2f degrees C\n",
temp_in, temp_out);

With these changes, the output now looks like the following:

/> ch ./temp_converter.ch 212 F C
212.00 degrees F is 100.00 degrees C
/> ch ./temp_converter.ch 0 C F
0.00 degrees C is 32.00 degrees F

Another improvement that could be made to the program would be to add support to and from temperatures specified in the Kelvin and/or Rankine temperature scales. While adding support for these additional temperature scales, another change that could be made would be to check for input temperature values that are below absolute zero.

Conclusion

As this article has shown Ch provides a very nice environment for learning C and for quickly developing and testing C programs features by showing how to easily write a small and useful Ch program.

Join the newsletter!

Or

Sign up to gain exclusive access to email subscriptions, event invitations, competitions, giveaways, and much more.

Membership is free, and your security and privacy remain protected. View our privacy policy before signing up.

Error: Please check your email address.

Tags programmingCprogramming language

More about Inc.Linux

Show Comments
[]