summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ashby <martin@ashbysoft.com>2023-02-11 17:35:26 +0000
committerMartin Ashby <martin@ashbysoft.com>2023-02-11 17:35:26 +0000
commitb782b3f9b677d2fcfdbf79a30b3fd4e8a0002aec (patch)
tree537ec6f9ddc220703a215995fda70e5e63592bb9
parentcabe1a14b31edce1a247c367f8e1d7265abec34e (diff)
downloadlearn-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.c113
-rw-r--r--ex5-7.c48
-rw-r--r--ex5-8.c58
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;
+}
diff --git a/ex5-7.c b/ex5-7.c
index 2d277ad..1457410 100644
--- a/ex5-7.c
+++ b/ex5-7.c
@@ -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;
diff --git a/ex5-8.c b/ex5-8.c
new file mode 100644
index 0000000..1f74a19
--- /dev/null
+++ b/ex5-8.c
@@ -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