Some Weighty Conversions – Solution

This month’s Exercise is to create a program that converts weight measurements by using this format:

nnnFT

Where nnn is a value, F is the unit to convert from, and T is the unit to convert to. This problem is more of an input-parsing exercise than a straight conversion.

For my solution, I use an if-else if-else structure to sift through the various permutations of K (kilos), P (pounds), and S (stone). The first step, however, is to pull out the relevant information.

To process the string I use the strtof() function. This function is far superior to the old atof() function; strtof() uses two pointers, illustrated in Figure 1.

Figure 1. How the strtof() function works

The first pointer, input, references the string containing the value — and the value must come first. The second pointer, which is the address of a pointer (convert in my example), will hold the location of the first non-value character in the string, which comes in handy for plucking out the conversion characters.

(I don’t cover the strtof() function specifically in this blog, though I do cover its relative strtod() in this blog post.)

After input is read, this statement converts the value:

w = strtof(input,&convert);

Variable w holds the floating point value stored in string input, with pointer variable convert holding the location of the next character after the value. To ensure that the input was valid, a test is performed on w:

if( w==0.0 && convert==input )
    error_exit();

When the value returned by strtof() is zero and both pointers are equal, the input contained no value. The code exits with an error message (error_exit()) when true.

After converting and checking the value, another test is performed to ensure that two characters are typed after the value, where convert is a pointer referencing the first character:

if( *convert=='\0' ||
    *convert=='\n' ||
    *(convert+1)=='\0' ||
    *(convert+1)=='\n')
{
    error_exit();
}

At this point, I’m assured that two characters are found after the value, so a series of tests are performed to examine these characters and output the proper results. If anything goes awry during these tests, control is thrust to the error_exit() function, which terminates the code.

Here is my solution:

2020_12-Exercise.c

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void error_exit(void)
{
    puts("Invalid input");
    exit(1);
}

int main()
{
    float w;
    char input[16];
    char *r,*convert;

    /* intro text */
    puts("Type a value to convert, suffixed by conversion types:");
    puts("K - kilos, P - pounds, S - stones");
    puts("Example: 2.0PK (convert 2.0 pounds to kilograms)");
    printf("Convert: ");

    /* gather input */
    r = fgets(input,16,stdin);
    if( r==NULL )
        error_exit();

    /* process input */
    w = strtof(input,&convert);
        /* text for nothing input */
    if( w==0.0 && convert==input )
        error_exit();
        /* confirm that conversion characters exist */
    if( *convert=='\0' ||
        *convert=='\n' ||
        *(convert+1)=='\0' ||
        *(convert+1)=='\n')
    {
        error_exit();
    }
        /* kilo conversions */
    if( toupper(*convert)=='K' )
    {
        if( toupper( *(convert+1))=='P' )
            printf("%.2f kilos is %.2f pounds\n",w,w*2.20462);
        else if( toupper( *(convert+1))=='S' )
            printf("%.2f kilos is %.2f stone\n",w,w*0.157473);
        else
            error_exit();
    }
        /* pounds conversions */
    else if( toupper(*convert)=='P' )
    {
        if( toupper( *(convert+1))=='K' )
            printf("%.2f pounds is %.2f kilos\n",w,w*0.453592);
        else if( toupper( *(convert+1))=='S' )
            printf("%.2f pounds is %.2f stone\n",w,w*0.0714286);
        else
            error_exit();
    }
        /* stone conversions */
    else if( toupper(*convert)=='S' )
    {
        if( toupper( *(convert+1))=='K' )
            printf("%.2f stone is %.2f kilos\n",w,w*6.35029);
        else if( toupper( *(convert+1))=='P' )
            printf("%.2f stone is %.2f pounds\n",w,w*14.0);
        else
            error_exit();
    }
    else
        error_exit();

    return(0);
}

The if-else if-else monster scours for permutations of K, P, and S. Then a nested if-else if-else structure scans for the other letter and handles bogus input. Conversions are made within the printf() statements that output the results. Various toupper() functions translate lowercase letters to uppercase.

Type a value to convert, suffixed by conversion types:
K - kilos, P - pounds, S - stones
Example: 2.0PK (convert 2.0 pounds to kilograms)
Convert: 103.5kp
103.50 kilos is 228.18 pounds

In the sample run above, 103.5 kilograms is converted into pounds: 228.18.

I hope your solution works and that proper output is generated.

Leave a Reply