From 78603c50f61f74624218459ad6d8e212d36e681f Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Thu, 3 Nov 2016 13:05:49 +0100 Subject: temperaturUmrechner --- .gitignore | 1 + Makefile | 15 ++++++ default.nix | 10 ++++ temperaturUmrechner.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 165 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 default.nix create mode 100644 temperaturUmrechner.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..41fbeb0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +**/result diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ae2159d --- /dev/null +++ b/Makefile @@ -0,0 +1,15 @@ +CC = gcc +CCFLAGS = -owall +INCLUDES = +PREFIX = /usr/local + +.PHONY: all install + +all: temperaturUmrechner + +install: + mkdir -p $(PREFIX)/bin + install -m 0755 -t $(PREFIX)/bin temperaturUmrechner + +temperaterUmrechner: + $(CC) $(INCLUDES) $(CCFLAGS) -o temperaturUmrechner temperaturUmrechner.c diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..665253c --- /dev/null +++ b/default.nix @@ -0,0 +1,10 @@ +{ stdenv +}: + +stdenv.mkDerivation { + name = "sysprak.exc"; + src = ./.; + preInstall = '' + sed -i s,/usr/local,$out, Makefile + ''; +} diff --git a/temperaturUmrechner.c b/temperaturUmrechner.c new file mode 100644 index 0000000..25ecc31 --- /dev/null +++ b/temperaturUmrechner.c @@ -0,0 +1,139 @@ +#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); +} -- cgit v1.2.3