An introduction to Ch: Implementing a temperature converter in Ch

Ch is a combined C shell and IDE

One additional change to this program is the first line—#include <string.h>—which tells Ch to incorporate the file string.h into the program. This file includes descriptions of string manipulation functions, like strcmp. Now, if this program is executed with an invalid input temperature scale, such as hello, it will display the following output:

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

But when 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'

Observe, however, that if the input temperature scale is specified as fahrenheit instead of Fahrenheit, the program will reject this as an invalid input temperature scale:

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

This behavior can be easily fixed by replacing the strcmp function with the strcasecmp function as follows:

if (strcasecmp(scale_in_raw, "Fahrenheit") == 0 ||
strcasecmp(scale_in_raw, "F") == 0 ||
strcasecmp(scale_in_raw, "Celsius") == 0 ||
strcasecmp(scale_in_raw, "C") == 0) {
printf("Input temperature scale: '%s'\n",
scale_in_raw);
} else {
printf("Invalid input temperature scale: '%s'\n",
scale_in_raw);
}

Functions

To verify whether a valid output temperature scale was specified, a similar if statement could easily be added to the program, but whenever any changes needed to be made to one if statement, the same changes would likely have to be made to the other if statement. Forgetting to make this change could introduce unintended errors to the program. A better approach would be to create a function that performed the task of validating whether a valid output temperature scale was specified. The basic version of such a function can be created as follows:

int which_scale(string_t scale) {
return -1;
}

These statements create a function called which_scale. This function takes as its input a single string variable named scale. The int keyword that precedes the function name, which_scale, indicates that this function returns an integer value when it completes. In the initial version, shown above, the function uses the C language return statement to return a value of -1.

To make the function more useful, it can be changed to return a value of 1 when the specified scale is Fahrenheit and 2 when specified scale is Celsius as follows:

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

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

With this change, the complete function is as follows:

int which_scale(string_t scale) {
if (strcasecmp(scale, "Fahrenheit") == 0 ||
strcasecmp(scale, "F") == 0) {
return 1;
}

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

	return -1;
}

To use this function to check whether the input temperature scale, stored in the variable scale_in_raw, was specified in Fahrenheit or Celsius, the following statements can be added to the main function:

scale_in = which_scale(scale_in_raw);
if (scale_in == 1 || scale_in == 2) {
printf("Input temperature scale: '%s'\n",
scale_in_raw);
} else {
printf("Invalid input temperature scale: '%s'\n",
scale_in_raw);
}

Here, the which_scale function is executed with the input temperature scale, stored in the variable scale_in_raw, as its input and the return value from the which_scale is stored in the variable scale_in (scale_in = which_scale(scale_in_raw)). The value returned by the which_scale function is then checked to see if it was either 1 (indicating that Fahrenheit was specified) or 2 (indicating that Celsius was specified). If the value returned by the which_scale function corresponds to either Fahrenheit or Celsius, then a message indicating which temperate scale was specified is printed out. Otherwise, an error message indicating that the specified temperature scale was invalid is printed out.

Similarly, the which_scale function can be used to check whether the output temperature scale, stored in the variable scale_out_raw, was specified in Fahrenheit or Celsius, by adding the following statements to the main function:

scale_out = which_scale(scale_out_raw);
if (scale_out == 1 || scale_out == 2) {
printf("Output temperature scale: '%s'\n",
scale_out_raw);
} else {
printf("Invalid output temperature scale: '%s'\n",
scale_out_raw);
}

Now that the program has been updated to check the values supplied for both the input and output temperature scales, one final input validation can be performed—to check whether the same value was specified for both the input and the output temperature scales. This can be accomplished using the following if statement:

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

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

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

int which_scale(string_t scale);

int which_scale(string_t scale) {

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

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

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

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

	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 == 1 || scale_in == 2) {
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 == 1 || scale_out == 2) {
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");
}
}

One additional change to the program is the addition of a statement just before the first line of the which_scale function:

int which_scale(string_t scale);

int which_scale(string_t scale) {

Although this statement looks nearly identical to the first line of the which_scale function, it has a different purpose. This statement is called a function prototype and defines what inputs a function will accept and what value a function returns. Although Ch does not require function prototypes, it is a good practice to include them in Ch programs because prototypes are required in well-written C programs.

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