diff options
author | Martin Ashby <martin@ashbysoft.com> | 2023-02-07 22:20:47 +0000 |
---|---|---|
committer | Martin Ashby <martin@ashbysoft.com> | 2023-02-07 22:20:47 +0000 |
commit | cabe1a14b31edce1a247c367f8e1d7265abec34e (patch) | |
tree | e66fd91f6682d084ea8484b1be43bd5631dc7610 | |
parent | 7fa502ba4e60ce762ab529996c66a1a831cb789f (diff) | |
download | learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.gz learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.bz2 learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.tar.xz learn-c-cabe1a14b31edce1a247c367f8e1d7265abec34e.zip |
Chapter 5
-rw-r--r-- | ex1-8.c | 2 | ||||
-rw-r--r-- | ex5-1.c | 97 | ||||
-rw-r--r-- | ex5-3.c | 20 | ||||
-rw-r--r-- | ex5-4.c | 23 | ||||
-rw-r--r-- | ex5-5.c | 20 | ||||
-rw-r--r-- | ex5-7.c | 111 | ||||
-rwxr-xr-x | run | 3 |
7 files changed, 274 insertions, 2 deletions
@@ -32,7 +32,7 @@ static struct res _loop(struct res res) { } else if (c == '\t') { res.tb++; } - __attribute__((musttail)) + //__attribute__((musttail)) return _loop(res); } @@ -0,0 +1,97 @@ +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> + +#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; i<PUSHBACK_MAX; i++) { + ret.pushback[i] = -1; + } + return ret; +} + +int getch(StreamWithPushback* swpb) { + if (swpb->pushback_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 @@ -0,0 +1,20 @@ +#include <stdio.h> + +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 @@ -0,0 +1,23 @@ +#include <stdio.h> + +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 @@ -0,0 +1,20 @@ +#include <stdio.h> + +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 @@ -0,0 +1,111 @@ +#include <stdio.h> +#include <string.h> + +// 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<nlines; i++) + printf("%s\n", lineptr[i]); +} + +void qsort(char* v[], int left, int right) { + int i, last; + void swap(char* v[], int i, int j); + if (left >= 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<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) { + s[i] = c; + } + if (c == '\n') { + s[i] = c; + ++i; + } + s[i] = '\0'; + return i; +}
\ No newline at end of file @@ -1,6 +1,7 @@ #!/usr/bin/env bash set -e -clang -Wall -Werror -o exe $@ +CC=gcc +${CC} -Wall -Werror -o exe $@ ./exe result=$? rm exe |