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:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | /*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:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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: