An introduction to Ch: Implementing a temperature converter in Ch

Ch is a combined C shell and IDE

Now, if this program is executed with an invalid input or output temperature scale, such as hello, it will display the following output:

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

Likewise, when the program is executed with the same input and output temperature scale, it will display 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, however, this program is executed with the command line arguments 212, F, C, it will display the following output:

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

Enumerations

Although the program can correctly determine whether the input and/or output temperature scale was specified as either Fahrenheit or Celsius, the program relies on the hard-coded values of 1 and 2 to represent Fahrenheit or Celsius, respectively. To make the program easier to maintain (and extend), a better approach would be to use named integer constants to represent these values. These types of constants can be created using C language enumerations.

A C language enumeration can be created using the enum keyword, which has the following syntax:

enum {
first constant = first value,
second constant = second value,
…
last constant = last value
};

The first constant is assigned the first value, the second constant is assigned the second value, and so on. (The values are optional, and if omitted, start from 0 and increase by 1).

Using the enum keyword, constant values to represent Fahrenheit or Celsius can be created as follows:

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

Once these constants have been crated, the which_scale function can be updated to use them as follows:

int which_scale(string_t scale) {

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

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

	return -1;
}

Next, the two if statements in the main function that check the value returned by the which_scale function can be updated as follows:

if (scale_in == SCALE_F || scale_in == SCALE_C) {
…
if (scale_out == SCALE_F || scale_out == SCALE_C) {

With these changes, the complete program looks like the following:

#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;
}

void 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) {
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("Input temperature: '%f' degrees\n",
temp_in);
} else {
printf("Invalid input temperature: '%s' degrees\n",
temp_raw);
}

		/* 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("Input temperature scale: '%s'\n",
scale_in_raw);
} else {
printf("Invalid input temperature scale: '%s'\n",
scale_in_raw);
}

		/* 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("Output temperature scale: '%s'\n",
scale_out_raw);
} else {
printf("Invalid output temperature scale: '%s'\n",
scale_out_raw);
}

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

	} else {
printf("Please specify the temperature and scales.\n");
}
}

Exiting on Errors

As noted above, there are several situations in which invalid or erroneous inputs may be supplied to the program. First, the user may not supply the input temperature, the input temperature’s scale, and/or the output temperature scale. Second, the specified temperature may not be a valid numerical value. Third, the input and output temperature scales may not be specified in Fahrenheit or Celsius. Finally, the input and output temperature scales may be the same.

When these situations occur, instead of continuing to execute, the program should report the error and terminate using the exit C function. For example, if the user does not supply the input temperature, the input temperature’s scale, and the output temperature scale, argc will have a value less than 4 (argc < 4). If this occurs, the program can terminate using the following if statement:

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

Here, the exit function is executed if argc has a value less than 4. The value of 1 that is supplied to the exit function (exit(1)), is known as the exit code. Generally, when a program completes without encountering any errors, it exits with an exit code of 0. If any errors occur, a program generally exits with an exit code of greater than 0. Because the failure to specify the input temperature, the input temperature’s scale, and the output temperature scale is an error, the exit function is supplied with an exit code of 1.

Similarly, the program can detect when a specified temperature is not a valid numerical value and terminate using the following if statement:

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

Because sscanf will return a value of 1 if a valid numerical value was supplied for the temperature (stored in temp_raw), this if statement uses the not-equal-to operator (!=) to check whether sscanf did not return a value of 1 (sscanf(temp_raw, "%f", &temp_in) != 1) and causes the program to exit with an exit code of 1 (exit(1)) whenever sscanf returns a value that does not equal 1.

To have the program exit when the input temperature scale is not specified in Fahrenheit or Celsius, the following if statement can be used:

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

This if statement uses the and operator (&&) to check whether (1) the input temperature scale, stored in scale_in, does not equal the temperature scale constant corresponding to Fahrenheit (scale_in != SCALE_F), and whether the input temperature scale does not equal the temperature scale constant corresponding to Celsius (scale_in != SCALE_C). If the input temperature scale does not equal either of these values, then an invalid temperature scale was specified, so the if statement causes the program to exit with an exit code of 1 (exit(1)). A similar if statement can be used to make the program exit when the output temperature scale is not specified in Fahrenheit or Celsius:

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

The program can also use the following if statement to exit when the input and output temperature scales are the same (scale_in == scale_out):

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

Finally, if every input was acceptable, the program can exit successfully with an exit code of 0, as follows:

exit(0);

Since the program now exits with an exit code, the return type of the main function also needs to be changed to return an integer to indicate that the main function will be return an integer value (such as 0 or 1) when it finishes:

int main (int argc, string_t argv[]) {

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
[]