From cabe1a14b31edce1a247c367f8e1d7265abec34e Mon Sep 17 00:00:00 2001 From: Martin Ashby Date: Tue, 7 Feb 2023 22:20:47 +0000 Subject: Chapter 5 --- ex1-8.c | 2 +- ex5-1.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ex5-3.c | 20 ++++++++++++ ex5-4.c | 23 ++++++++++++++ ex5-5.c | 20 ++++++++++++ ex5-7.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ run | 3 +- 7 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 ex5-1.c create mode 100644 ex5-3.c create mode 100644 ex5-4.c create mode 100644 ex5-5.c create mode 100644 ex5-7.c diff --git a/ex1-8.c b/ex1-8.c index 7e8c3bd..3ba90d0 100644 --- a/ex1-8.c +++ b/ex1-8.c @@ -32,7 +32,7 @@ static struct res _loop(struct res res) { } else if (c == '\t') { res.tb++; } - __attribute__((musttail)) + //__attribute__((musttail)) return _loop(res); } diff --git a/ex5-1.c b/ex5-1.c new file mode 100644 index 0000000..9a43c00 --- /dev/null +++ b/ex5-1.c @@ -0,0 +1,97 @@ +#include +#include +#include + +#define PUSHBACK_MAX 10 +typedef struct { + FILE* stream; + int pushback[PUSHBACK_MAX]; + int pushback_ix; +} StreamWithPushback; + +StreamWithPushback swpb_new(FILE* f) { + StreamWithPushback ret; + ret.stream = f; + ret.pushback_ix = 0; + for (int i=0; ipushback_ix > 0) { + int ch = swpb->pushback[swpb->pushback_ix]; + swpb->pushback_ix--; + return ch; + } + return getc(swpb->stream); +} + +void ungetch(StreamWithPushback* swpb, int ch) { + if (swpb->pushback_ix >= PUSHBACK_MAX) { + fprintf(stderr, "pushback buffer was full!\n"); + exit(1); + } + swpb->pushback[swpb->pushback_ix] = ch; + swpb->pushback_ix++; +} + +/* getint: get next integer from input into *pn */ +int getint(StreamWithPushback* swpb, int *pn) { + int c, sign; + + while (isspace(c = getch(swpb))) {} + + if (!isdigit(c) && c != EOF && c != '+' && c != '-') { + ungetch(swpb, c); + return 0; + } + + sign = (c == '-') ? -1 : 1; + if (c == '+' || c == '-') { + c = getch(swpb); + // If c isn't then a digit, then we don't have a number. + if (!isdigit(c)) { + ungetch(swpb, c); + // Push the sign character back as well, don't consume it + ungetch(swpb, sign == -1 ? '-' : '+'); + return 0; + } + } + + for (*pn = 0; isdigit(c); c = getch(swpb)) { + *pn = 10 * *pn + (c - '0'); + } + *pn *= sign; + + if (c != EOF) { + ungetch(swpb, c); + } + return c; +} + +#ifndef test + +int main(void) { + int p, x; + StreamWithPushback swpb = swpb_new(stdin); + while ((x = getint(&swpb, &p)) != EOF) { + if (x > 0) { + printf("%d\n", p); + } else { + printf("not a number!\n"); + } + } +} + +#else + +#include "CuTest.h" + +// I could write unit tests here, using fmemopen +// instead of reading something off the filesystem. + +// But I can't be bothered. + +#endif \ No newline at end of file diff --git a/ex5-3.c b/ex5-3.c new file mode 100644 index 0000000..826a581 --- /dev/null +++ b/ex5-3.c @@ -0,0 +1,20 @@ +#include + +void z_strcat(char* s, char* t) { + // Skip to the end of s + for (; *s != '\0'; s++) {} + // Copy over t + for (; *t != '\0'; t++, s++) { + *s = *t; + } + // Ensure null terminator + *s = '\0'; +} + +int main(void) { + char buf[100] = ""; + z_strcat(buf, "foo"); + printf("%s\n", buf); + z_strcat(buf, "bar"); + printf("%s\n", buf); +} \ No newline at end of file diff --git a/ex5-4.c b/ex5-4.c new file mode 100644 index 0000000..d32e965 --- /dev/null +++ b/ex5-4.c @@ -0,0 +1,23 @@ +#include + +int strend(char* const s, char* const t) { + char* s_p = s; + char* t_p = t; + for (; *s_p != '\0'; s_p++); + for (; *t_p != '\0'; t_p++); + for (; !(s_p == s || t_p == t); s_p--, t_p--) { + if (*s_p != *t_p) { + return 0; + } + } + return t_p == t; +} + +int main(void) { + printf("0==%d\n", strend("foo", "bar")); + printf("1==%d\n", strend("foo", "foo")); + printf("1==%d\n", strend("xyzfoo", "foo")); + printf("0==%d\n", strend("foo", "xyzfoo")); + printf("1==%d\n", strend("foo", "")); + printf("1==%d\n", strend("", "")); +} \ No newline at end of file diff --git a/ex5-5.c b/ex5-5.c new file mode 100644 index 0000000..a6af275 --- /dev/null +++ b/ex5-5.c @@ -0,0 +1,20 @@ +#include + +char* z_strncpy(char *dest, char *src, size_t n) { + char* max = dest + n; + for (; *src != '\0' && dest < max; dest++, src++) { + *dest = *src; + } + for (; dest < max; dest++) { + *dest = '\0'; + } + return dest; +} + +int main(void) { + char buf[100] = ""; + z_strncpy(buf, "Hello, World", 5); + printf("Hello = %s\n", buf); + z_strncpy(buf, "Hello, World", 20); + printf("Hello, World = [%s]\n", buf); +} \ No newline at end of file diff --git a/ex5-7.c b/ex5-7.c new file mode 100644 index 0000000..2d277ad --- /dev/null +++ b/ex5-7.c @@ -0,0 +1,111 @@ +#include +#include + +// 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 MAXLINES 5000 + +int readlines(char* lineptr[], int nlines); + +void writelines(char* lineptr[], int nlines); + +void qsort(char* lineptr[], int left, int right); + +int main() { + int nlines; + char* lineptr[MAXLINES]; + if ((nlines = readlines(lineptr, MAXLINES)) >= 0) { + qsort(lineptr, 0, nlines-1); + writelines(lineptr, nlines); + return 0; + } else { + fprintf(stderr, "error: input too big to sort\n"); + return 1; + } +} + +#define MAXLEN 1000 + +int z_getline(char*, int); +char* alloc(int); + +int readlines(char* lineptr[], int maxlines) { + int len; + int nlines = 0; + char* p; + char line[MAXLEN]; + while ((len = z_getline(line, MAXLEN)) > 0) { + if (nlines >= maxlines || (p = alloc(len)) == NULL) { + return -1; + } else { + line[len-1] = '\0'; // delete newline + strcpy(p, line); + lineptr[nlines++] = p; + } + } + return nlines; +} + +void writelines(char* lineptr[], int nlines) { + for (int i=0; i= right) { + return; + } + swap(v, left, (left+right)/2); + last = left; + for (i=left+1; i<=right; i++) { + if (strcmp(v[i], v[left]) < 0) { + swap(v, ++last, i); + } + } + swap(v, left, last); + qsort(v, left, last-1); + qsort(v, last+1, right); +} + +void swap(char* v[], int i, int j) { + char* temp = v[i]; + v[i] = v[j]; + v[j] = temp; +} + + +/* getline: read a line into s, return length */ +int z_getline(char s[], int lim) { + int c, i; + for (i=0; i