diff options
author | Tomasz Kramkowski <tk@the-tk.com> | 2016-04-01 19:30:35 +0200 |
---|---|---|
committer | Tomasz Kramkowski <tk@the-tk.com> | 2016-04-01 19:30:35 +0200 |
commit | 4630e2d37ba0a104b1bbebfebe1bedcbebd382ac (patch) | |
tree | 7bd1469461e30137cd8a0e01248ac40dfa9ba1af | |
parent | dbdc4df860a4a8bdae8eff1de7d6f478df486165 (diff) | |
download | c-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.tar.gz c-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.tar.xz c-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.zip |
rot.c: Fix this terribly broken rot
-rw-r--r-- | rot.c | 130 |
1 files changed, 111 insertions, 19 deletions
@@ -8,32 +8,124 @@ * along with this program. If not, see [http://www.gnu.org/licenses/]. */ -#include <stdio.h> -#include <string.h> #include <ctype.h> +#include <errno.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdio.h> #include <stdlib.h> +#include <stdnoreturn.h> +#include <string.h> -int main(int argc, char **argv) +#define ACHAR_CNT 26 + +static noreturn void die(char *fmt, ...) { - if (argc != 3) { - fprintf(stderr, "Usage: <text> <rotation>\a\n"); - exit(1); - } + va_list ap; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + exit(EXIT_FAILURE); +} + +static int aclamp(long val) +{ + while (val < 0) + val += ACHAR_CNT; + + return val % ACHAR_CNT; +} + +static int getrot(const char *str) +{ + long val; + char *endptr; + + if (!*str) + die("Invalid argument '%s'\n", str); + + errno = 0; + val = strtol(str, &endptr, 10); + if (errno) + die("Invalid argument '%s': %s", str, strerror(errno)); + if (*endptr) + die("Invalid argument '%s'\n", str); + + return aclamp(val); +} - int rot = strtol(argv[2], NULL, 10); - unsigned length = strlen(argv[1]); - - for (unsigned i = 0; i < length; i++) { - if (isalpha(argv[1][i])) { - if (argv[1][i] - 'A' < 26) - putchar((argv[1][i] - 'A' + rot) % 26 + 'A'); - else - putchar((argv[1][i] - 'a' + rot) % 26 + 'a'); - } else - putchar(argv[1][i]); +static int chval(int c) +{ + switch (tolower(c)) { + case 'a': return 0; + case 'b': return 1; + case 'c': return 2; + case 'd': return 3; + case 'e': return 4; + case 'f': return 5; + case 'g': return 6; + case 'h': return 7; + case 'i': return 8; + case 'j': return 9; + case 'k': return 10; + case 'l': return 11; + case 'm': return 12; + case 'n': return 13; + case 'o': return 14; + case 'p': return 15; + case 'q': return 16; + case 'r': return 17; + case 's': return 18; + case 't': return 19; + case 'u': return 20; + case 'v': return 21; + case 'w': return 22; + case 'x': return 23; + case 'y': return 24; + case 'z': return 25; } - putchar('\n'); + return -1; +} + +static int valch(int c, bool upper) +{ + static const char chars[] = "abcdefghijklmnopqrstuvwxyz"; + int ret; + + if (c < 0 || c > 25) + return 0; + + ret = chars[aclamp(c)]; + + if (upper) + ret = toupper(ret); + + return ret; +} + +static int rot(int c, int r) +{ + return valch(aclamp(chval(c) + r), isupper(c)); +} + +int main(int argc, char **argv) +{ + int r, c; + + if (argc != 2) + die("Usage: %s <rotation>\n", argv[0]); + + r = getrot(argv[1]); + + while (c = getchar(), c != EOF) { + if (isalpha(c)) + putchar(rot(c, r)); + else + putchar(c); + } return 0; } |