aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomasz Kramkowski <tk@the-tk.com>2016-04-01 19:30:35 +0200
committerTomasz Kramkowski <tk@the-tk.com>2016-04-01 19:30:35 +0200
commit4630e2d37ba0a104b1bbebfebe1bedcbebd382ac (patch)
tree7bd1469461e30137cd8a0e01248ac40dfa9ba1af
parentdbdc4df860a4a8bdae8eff1de7d6f478df486165 (diff)
downloadc-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.tar.gz
c-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.tar.xz
c-stuff-4630e2d37ba0a104b1bbebfebe1bedcbebd382ac.zip
rot.c: Fix this terribly broken rot
-rw-r--r--rot.c130
1 files changed, 111 insertions, 19 deletions
diff --git a/rot.c b/rot.c
index c7c6771..985cc69 100644
--- a/rot.c
+++ b/rot.c
@@ -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;
}