diff options
author | Martin Ashby <martin@ashbysoft.com> | 2023-02-11 17:35:26 +0000 |
---|---|---|
committer | Martin Ashby <martin@ashbysoft.com> | 2023-02-11 17:35:26 +0000 |
commit | b782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec (patch) | |
tree | 537ec6f9ddc220703a215995fda70e5e63592bb9 | |
parent | cabe1a14b31edce1a247c367f8e1d7265abec34e (diff) | |
download | learn-c-main.tar.gz learn-c-main.tar.bz2 learn-c-main.tar.xz learn-c-main.zip |
Exercise 5.10main
-rw-r--r-- | ex5-10.c | 113 | ||||
-rw-r--r-- | ex5-7.c | 48 | ||||
-rw-r--r-- | ex5-8.c | 58 |
3 files changed, 195 insertions, 24 deletions
diff --git a/ex5-10.c b/ex5-10.c new file mode 100644 index 0000000..c4afccd --- /dev/null +++ b/ex5-10.c @@ -0,0 +1,113 @@ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> + +#define NUMBER '0' +#define MAXLINE 1000 +#define MAXVAL 100 + +int getop(char[]); + +void push(double); +double pop(void); +void clear(void); +double peek(void); + +// Naïve implementation of remainder operation +double frem(double f1, double f2) { + return f1 - (f2 * (int)(f1 / f2)); +} + +/** + * Reverse polish notation calculator + */ +int main(int argc, char* argv[]) { + if (argc <= 1) { + fprintf(stderr, "Usage: rpol EXPR..."); + return 1; + } + argv++; // Skip program name + double op2; + for (; *argv != NULL; argv++) { + char* tok = *argv; + int type = getop(tok); + switch (type) { + case NUMBER: + push(atof(tok)); + 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 '%': + op2 = pop(); + if (op2 != 0.0) + push(frem(pop(), op2)); + else + printf("error: zero division attempted!\n"); + break; + case '~': + clear(); + break; + default: + printf("unknown command %s\n", tok); // Just ignore it? + break; + } + } + + printf("\t%.8g\n", pop()); + 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; + } +} + +double peek(void) { + if (sp >= 0) { + return val[sp-1]; + } else { + printf("error, empty stack\n"); + return 0.0; + } +} + +void clear(void) { + sp = 0; +} + +int getop(char s[]) { + char c = s[0]; + if (!isdigit(c) && c != '.') + return c; + return NUMBER; +} @@ -3,25 +3,25 @@ // An extremely simple allocation system. // Memory must be freed in the reverse order it was allocated. -#define ALLOCSIZE 10000 - -static char allocbuf[ALLOCSIZE]; -static char *allocp = allocbuf; - -char *alloc(int n) { - if (allocbuf + ALLOCSIZE - allocp >= n) { - allocp += n; - return allocp - n; - } else { - return NULL; - } -} - -void afree(char *p) { - if (p >= allocbuf && p < allocbuf + ALLOCSIZE) { - allocp = p; - } -} +// #define ALLOCSIZE 10000 + +// static char allocbuf[ALLOCSIZE]; +// static char *allocp = allocbuf; + +// char *alloc(int n) { +// if (allocbuf + ALLOCSIZE - allocp >= n) { +// allocp += n; +// return allocp - n; +// } else { +// return NULL; +// } +// } + +// void afree(char *p) { +// if (p >= allocbuf && p < allocbuf + ALLOCSIZE) { +// allocp = p; +// } +// } #define MAXLINES 5000 @@ -47,7 +47,7 @@ int main() { #define MAXLEN 1000 int z_getline(char*, int); -char* alloc(int); +// char* alloc(int); int readlines(char* lineptr[], int maxlines) { int len; @@ -71,9 +71,10 @@ void writelines(char* lineptr[], int nlines) { printf("%s\n", lineptr[i]); } -void qsort(char* v[], int left, int right) { - int i, last; - void swap(char* v[], int i, int j); +void swap(char* v[], int i, int j); + +void qsort(char* v[], const int left, const int right) { + int i, last; if (left >= right) { return; } @@ -95,7 +96,6 @@ void swap(char* v[], int i, int j) { v[j] = temp; } - /* getline: read a line into s, return length */ int z_getline(char s[], int lim) { int c, i; @@ -0,0 +1,58 @@ +#include <stdio.h> +#define NDEBUG +#include <assert.h> + +static char daytab[2][13] = { + {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} +}; + +/* day_of_year: set day of year from month & day */ +int day_of_year(int year, int month, int day) +{ + assert(month >= 1); + assert(month <= 12); + + int i, leap; + + leap = (year%4 == 0 && year%100 != 0) || year%400 == 0; + + assert(day >= 1); + assert(day <= *(*(daytab+leap) + month)); + + for (i = 1; i < month; i++) + day += *(*(daytab+leap) + i); + return day; +} + +/* month_day: set month, day from day of year */ +void month_day(int year, int yearday, int *pmonth, int *pday) +{ + int i, leap; + + leap = (year%4 == 0 && year%100 != 0) || year%400 == 0; + + assert(yearday >= 1); + assert(yearday <= (leap ? 366 : 365)); + + for (i = 1; yearday > *(*(daytab+leap)+i); i++) + yearday -= *(*(daytab+leap)+i); + *pmonth = i; + *pday = yearday; +} + +int main(void) { + // Add error checking eh + int doy, dom, month; + doy = day_of_year(2022, 2, 8); + month_day(2022, doy, &month, &dom); + + printf("2022-02-08 doy=%d month=%d dom=%d\n", doy, month, dom); + + doy = day_of_year(2022, 0, 8); + doy = day_of_year(2022, 13, 8); + doy = day_of_year(2022, 12, 0); + doy = day_of_year(2022, 12, 32); + doy = day_of_year(2022, 2, 29); + doy = day_of_year(2024, 2, 29); // This one is ok +}
\ No newline at end of file |