#include #include #include #include #include /* Supported units and string conversion */ typedef enum TemperatureUnit { CELSIUS, DELISLE, FARENHEIT, KELVIN, RANKINE } TemperatureUnit; const TemperatureUnit temperatureUnits[] = { CELSIUS, DELISLE, FARENHEIT, KELVIN, RANKINE }; const char* temperatureUnitNames[] = { "Celsius", "Delisle", "Farenheit", "Kelvin", "Rankine" }; /* Conversion table to kelvin */ const double kelvinMult[] = {1., -2. / 3., 5. / 9., 1, 5. / 9.}; const double kelvinAdd[] = {273.15, 373.15, 255.37, 0, 0}; static int const maxUnitLength = 31; // Maximum Length of members of temperatureUnitNames (not counting trailing \0) static int const unknownUnit = -1; // Ugh. void printUsage() { printf("usage: temperaturUmrechner {-f|--from} {-t|--to} [ [...]]\n" ); } TemperatureUnit parseUnit(char str[]) { char lowerUnit[maxUnitLength + 1]; char lowerStr[maxUnitLength + 1]; memset(lowerStr, '\0', maxUnitLength + 1); strncpy(lowerStr, str, maxUnitLength); for (int i = 0; i < maxUnitLength; i++) { if (lowerStr[i] == '\0') break; lowerStr[i] = tolower(lowerStr[i]); } for (int unit = 0; unit < (int)( sizeof(temperatureUnits) / sizeof(TemperatureUnit) ); unit++) { memset(lowerUnit, '\0', maxUnitLength + 1); for (int i = 0; i < maxUnitLength; i++) { if (temperatureUnitNames[unit][i] == '\0') break; lowerUnit[i] = tolower(temperatureUnitNames[unit][i]); } if (strcmp(lowerUnit, lowerStr) == 0) return temperatureUnits[unit]; } return unknownUnit; } double convert(double value, TemperatureUnit fromUnit, TemperatureUnit toUnit) { int fromUnitIndex = -1; int toUnitIndex = -1; for (int unit = 0; unit < (int)( sizeof(temperatureUnits) / sizeof(TemperatureUnit) ); unit++) { if (temperatureUnits[unit] == fromUnit) fromUnitIndex = unit; if (temperatureUnits[unit] == toUnit) toUnitIndex = unit; if (fromUnitIndex != -1 && toUnitIndex != -1) break; } if (fromUnitIndex == -1 || toUnitIndex == -1) abort(); return (value * kelvinMult[fromUnitIndex] + kelvinAdd[fromUnitIndex]) / kelvinMult[toUnitIndex] - kelvinAdd[toUnitIndex]; } void main(int argc, char* argv[]) { TemperatureUnit fromUnit = unknownUnit; TemperatureUnit toUnit = unknownUnit; while (1) { int c; int optionIndex = 0; static struct option longOptions[] = { {"from", required_argument, 0, 'f'}, {"to", required_argument, 0, 't'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "f:t:h", longOptions, &optionIndex); if (c == -1) break; switch (c) { case 'f': fromUnit = parseUnit(optarg); break; case 't': toUnit = parseUnit(optarg); break; case 'h': printUsage(); exit(0); break; default: printUsage(); } } if (fromUnit == unknownUnit) fprintf(stderr, "Unknown (or unset) unit to convert from\n"); if (toUnit == unknownUnit) fprintf(stderr, "Unknown (or unset) unit to convert to\n"); if (toUnit == unknownUnit || fromUnit == unknownUnit) { printUsage(); exit(2); } for (double value;optind < argc;optind++) { sscanf(argv[optind], "%lf", &value); printf("%.3g\n", convert(value, fromUnit, toUnit)); } exit(0); }