diff options
author | Martin Ashby <martin@ashbysoft.com> | 2022-11-21 20:25:15 +0000 |
---|---|---|
committer | Martin Ashby <martin@ashbysoft.com> | 2022-11-21 20:25:15 +0000 |
commit | 5a72e2df2d68116241cf053b78a0f78135b02e7b (patch) | |
tree | 413d629ebbeaf58697239d426194981b7b5f60c9 | |
parent | db6e9bac370093b13cfb6f0b81ac066fed64b004 (diff) | |
download | learn-c-5a72e2df2d68116241cf053b78a0f78135b02e7b.tar.gz learn-c-5a72e2df2d68116241cf053b78a0f78135b02e7b.tar.bz2 learn-c-5a72e2df2d68116241cf053b78a0f78135b02e7b.tar.xz learn-c-5a72e2df2d68116241cf053b78a0f78135b02e7b.zip |
Added ex4-2 and ex4-3
-rw-r--r-- | ex4-2.c | 130 | ||||
-rw-r--r-- | ex4-3.c | 113 |
2 files changed, 243 insertions, 0 deletions
@@ -0,0 +1,130 @@ +#include <stdio.h> + +/*static int _strlen(char s[]) { + int i; + for (i=0; s[i] != '\0'; i++) {} + return i; +}*/ + +/*static int _isspace(char s) { + return s == ' ' || s == '\t'; +}*/ + +static int _isdigit(char s) { + return '0' <= s && s <= '9'; +} + +static int _abs(int a) { + if (a >=0) { + return a; + } else { + return -1 * a; + } +} + +static int _intval(char s) { + return s - '0'; +} + +static int _isupper(char s) { + return 'A' <= s && s <= 'Z'; +} + +static char _tolower(char s) { + static int diff = 'A' - 'a'; + if (_isupper(s)) { + return s - diff; + } else { + return s; + } +} + + +static int _atoi_internal(char s[], int n) { + if (s == NULL || *s == '\0' || !_isdigit(*s)) { + return n; + } + __attribute__((musttail)) // Functional programinng enabler :) + return _atoi_internal(s + 1, (10 * n) + _intval(*s)); +} +/** + * Converts a string to an integer + * string must be null terminated + * overflow isn't detected, int is the limit + */ +int _atoi(char s[]) { + int i = 0; + int sign = (s[i] == '-') ? -1 : 1; + if (s[i] == '+' || s[i] == '-') + i++; + return _atoi_internal(s + i, 0) * sign; +} + +/** + * Converts a string to a double + * + * string must be null terminated. + * overflow isn't detected, and double precision is the limit. + */ +double _atof(char s[]) { + double val, power, ee; + int i = 0; + int sign = (s[i] == '-') ? -1 : 1; + if (s[i] == '+' || s[i] == '-') + i++; + for (val = 0.0; _isdigit(s[i]); i++) + val = 10.0 * val + _intval(s[i]); + if (s[i] == '.') + i++; + for (power = 1.0; _isdigit(s[i]); i++) { + val = 10.0 * val + _intval(s[i]); + power *= 10.0; + } + ee = 1.0; + if (_tolower(s[i]) == 'e') { + i++; + int exponent = _atoi(s + i); + if (exponent >= 0) { + for (int j=0;j<_abs(exponent);j++) ee *= 10.0; + } else { + for (int j=0;j<_abs(exponent);j++) ee /= 10.0; + } + } + return (sign * val / power) * ee; + +} + +void testb(char s[]) { + printf("atoi s = [%s] result = [%d]\n", s, _atoi(s)); +} + +void test(char s[]) { + printf("atof s = [%s] result = [%lf]\n", s, _atof(s)); +} + +int main(void) { + test(""); + test("gibber"); + test("\0"); + test("1"); + test("1.0"); + test("99.0"); + test("-10.0"); + test("+11.0"); + test("++11.0"); + test("-11111111111111111111111111111111111111111111111111111111111111111111111111111111111.1"); + + testb("gibber"); + testb(""); + testb("\0"); + testb("1"); + testb("1.5"); + testb("+2.6"); + testb("-7.8"); + testb("--7.8"); + + test("+11.0e5"); + test("2.75345e3"); + test("2.75345e-3"); + test("2.75345E-3"); +}
\ No newline at end of file @@ -0,0 +1,113 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#define NUMBER '0' +#define MAXOP 100 +#define MAXVAL 100 + +int getop(char[]); +void push(double); +double pop(void); + +/** + * Reverse polish notation calculator + */ +int main(void) { + int type; + double op2; + char s[MAXOP]; + while ((type = getop(s)) != EOF) { + switch (type) { + case NUMBER: + push(atof(s)); + break; + case '+': + push(pop() + pop()); + break; + case '*': + push(pop() * pop()); + break; + case '-': + op2 = pop(); + push(pop() - op2); + break; + case '/': + op2 = pop(); + if (op2 != 0.0) + push(pop() / op2); + else + printf("error: zero division attempted!\n"); + break; + case '\n': + printf("\t%.8g\n", pop()); + break; + default: + printf("unknown command %s\n", s); + break; + } + } + return 0; +} + + +int sp; // Stack position +double val[MAXVAL]; // Value stack +void push(double f) { + if (sp < MAXVAL) { + val[sp++] = f; + } else { + printf("error, stack full\n"); + } +} + +double pop(void) { + if (sp >= 0) { + return val[--sp]; + } else { + printf("error, empty stack\n"); + return 0.0; + } +} + + +int getch(void); +void ungetch(int); + +int getop(char s[]) { + int i,c; + // Skip to teh first non-space or tab character + while ((s[0] = c = getch()) == ' ' || c == '\t'); + // Then add a null for some reason? + s[1] = '\0'; + // if it's not a part of a number, it's an operation + if (!isdigit(c) && c != '.') + return c; + // Integer part + i = 0; + if (isdigit(c)) + while (isdigit(s[++i] = c = getch())); + // fraction part + if (c == '.') + while (isdigit(s[++i] = c = getch())); + s[i] = '\0'; + if (c != EOF) + ungetch(c); + return NUMBER; +} + +#define BUFSIZE 100 + +char buf[BUFSIZE]; // buffer for ungetch +int bufp = 0; // next free in buf + +int getch(void) { + return (bufp > 0) ? buf[--bufp] : getchar(); +} + +void ungetch(int c) { + if (bufp >= BUFSIZE) + printf("ungetch: buffer full\n"); + else + buf[bufp++] = c; +}
\ No newline at end of file |