I wanted to explore a further level of switching to implement a sub level menu within a main switch option, by adding to my Imperial to metric units converter. This allows extra functionality to a handy program - a two way units conversion choice.

Although trial and error placement is slow, it does let you think more about a program's operation, so help the learning curve, rather than just google an answer. The first working version program code is:

/*units converter for dist, vol or mass*/

#include <stdio.h>

float km; /*= 1;*/

float miles; /*= 1.60934 * km ;*/

float litre; /*= 1;*/

float pints; /*= (1.75975 / litre);*/

float gallons; /*= (8 * pints);*/

float kg; /*= 1;*/

float lb; /* = (2.204622 * kg);*/

char line[10]; /*input value array space */

char operator; /* menu operator the user specified */

float value; /* input value the user specified */

float result;

int main()

{

while (1)

{

printf("program to convert Imperial units to metric. Enter menu option: \n");

printf("1: km to miles\n");

printf("2: litres to pints\n");

printf("3: kg to pounds\n");

printf("q: quit\n");

fgets(line, sizeof(line), stdin);

sscanf(line, "%c", &operator);

if ((operator == 'q') || (operator == 'Q'))

break;

switch (operator)

{

case '1':

printf("1: convert km to miles. Enter km value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value / 1.60934;

printf("%f km is %0.3f miles \n\n", value, result);

break;

case '2':

printf("1: convert litres to pints. Enter litre value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value * 1.75975;

gallons = result/8;

printf("%0.3f litres is %0.3f pints or %0.3f gallons\n\n", value, result, gallons );

break;

case '3':

printf("3: convert kg to pounds. Enter kg value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value * 2.204622;

printf("%0.3f kg is %0.3f pounds \n\n", value, result);

break;

default:

{

printf("Invalid key, try again! %c\n\n", operator);

break;

}

}

}

printf("\n"); /*tidy cmd line*/

return (0);

}

This offers only metric to Imperial units conversion at present:

$ ./unitsconverter

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

1

1: convert km to miles. Enter km value: 1

1.000000 km is 0.621 miles

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

w

Invalid key, try again! w

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

q

Now it was just finding the correct format using clues from the above switch cases - with breaks in the right places - to make the extra nested switch options behave as desired. The first working case 1 sub menu code is shown below so you can see how it enters the first case option and breaks out to the main menu after either choice is completed:

int main()

{

while (1)

{

printf("program to convert Imperial units to metric. Enter menu option: \n");

printf("1: km to miles\n");

printf("2: litres to pints\n");

printf("3: kg to pounds\n");

printf("q: quit\n");

fgets(line, sizeof(line), stdin);

sscanf(line, "%c", &operator);

if ((operator == 'q') || (operator == 'Q'))

break;

switch (operator)

{

case '1':

printf("Want to (k) convert km to miles or (m) miles to km?: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%c", &operator);

switch (operator)

{

case 'k':

printf("k: convert km to miles. Enter km value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value / 1.60934;

printf("%f km is %0.3f miles \n\n", value, result);

break;

case 'm':

printf("m: convert miles to km. Enter miles value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value * 1.60934;

printf("%f m is %0.3f km \n\n", value, result);

break;

}

break;

case '2':

printf("2: convert litres to pints. Enter litre value: ");

fgets(line, sizeof(line), stdin);

sscanf(line, "%f", &value);

result = value * 1.75975;

gallons = result/8;

printf("%0.3f litres is %0.3f pints or %0.3f gallons\n\n", value, result, gallons );

break;

This shows both extra options working as required:

$ ./unitsconverter2

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

1

Want to (k) convert km to miles or (m) miles to km?: k

k: convert km to miles. Enter km value: 1

1.000000 km is 0.621 miles

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

1

Want to (k) convert km to miles or (m) miles to km?: m

m: convert miles to km. Enter miles value: 1

1.000000 m is 1.609 km

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

Invalid key, try again! w

program to convert Imperial units to metric. Enter menu option:

1: km to miles

2: litres to pints

3: kg to pounds

q: quit

q

Now it's just a case of pasting the same format to the other 2 options and re-arranging the formulae and units.

The exit beaks from the final main case 3 have to be correctly placed with {}'s to account for the default already in place: