From 8e72dcc573264190f7638a22e710aa83c7f40e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20-rsm-=20Marek?= Date: Thu, 4 Jul 2024 04:47:52 +0200 Subject: [PATCH] Exc. 6_01 --- chapter_6.structures/6_1.getword/Makefile | 3 + chapter_6.structures/6_1.getword/binsearch.c | 21 ++++ chapter_6.structures/6_1.getword/binsearch.h | 12 ++ chapter_6.structures/6_1.getword/getch.c | 25 +++++ chapter_6.structures/6_1.getword/getch.h | 9 ++ chapter_6.structures/6_1.getword/getword.c | 106 ++++++++++++++++++ chapter_6.structures/6_1.getword/getword.h | 7 ++ chapter_6.structures/6_1.getword/main.c | 59 ++++++++++ .../6_1.getword/tests/0_getch.tin | 9 ++ .../6_1.getword/tests/0_getch.tout | 2 + .../6_1.getword/tests/1_main.tin | 59 ++++++++++ .../6_1.getword/tests/1_main.tout | 7 ++ .../6_1.getword/tests/2_binsearch.tin | 21 ++++ .../6_1.getword/tests/2_binsearch.tout | 7 ++ chapter_6.structures/Makefile | 3 + 15 files changed, 350 insertions(+) create mode 100644 chapter_6.structures/6_1.getword/Makefile create mode 100644 chapter_6.structures/6_1.getword/binsearch.c create mode 100644 chapter_6.structures/6_1.getword/binsearch.h create mode 100644 chapter_6.structures/6_1.getword/getch.c create mode 100644 chapter_6.structures/6_1.getword/getch.h create mode 100644 chapter_6.structures/6_1.getword/getword.c create mode 100644 chapter_6.structures/6_1.getword/getword.h create mode 100644 chapter_6.structures/6_1.getword/main.c create mode 100644 chapter_6.structures/6_1.getword/tests/0_getch.tin create mode 100644 chapter_6.structures/6_1.getword/tests/0_getch.tout create mode 100644 chapter_6.structures/6_1.getword/tests/1_main.tin create mode 100644 chapter_6.structures/6_1.getword/tests/1_main.tout create mode 100644 chapter_6.structures/6_1.getword/tests/2_binsearch.tin create mode 100644 chapter_6.structures/6_1.getword/tests/2_binsearch.tout create mode 100644 chapter_6.structures/Makefile diff --git a/chapter_6.structures/6_1.getword/Makefile b/chapter_6.structures/6_1.getword/Makefile new file mode 100644 index 0000000..da69ca2 --- /dev/null +++ b/chapter_6.structures/6_1.getword/Makefile @@ -0,0 +1,3 @@ +BINARY=getword + +include ../../Exercise_incl.mk diff --git a/chapter_6.structures/6_1.getword/binsearch.c b/chapter_6.structures/6_1.getword/binsearch.c new file mode 100644 index 0000000..207b7bd --- /dev/null +++ b/chapter_6.structures/6_1.getword/binsearch.c @@ -0,0 +1,21 @@ +# include +# include "binsearch.h" + +/* binsearch: find word in tab[0]...tab[n-1] */ +int binsearch (char *word, struct key tab[], int n) +{ + int cond; + int low, high, mid; + low = 0; + high = n - 1; + while (low <= high) { + mid = (low+high) / 2; + if ((cond = strcmp(word, tab[mid].word)) < 0) + high = mid - 1; + else if (cond > 0) + low = mid + 1; + else + return mid; + } + return -1; +} diff --git a/chapter_6.structures/6_1.getword/binsearch.h b/chapter_6.structures/6_1.getword/binsearch.h new file mode 100644 index 0000000..8d53dbe --- /dev/null +++ b/chapter_6.structures/6_1.getword/binsearch.h @@ -0,0 +1,12 @@ +# ifndef BINSEARCH_H +# define BINSEARCH_H + +struct key { + char *word; + int count; +}; + +/* binsearch: find word in tab[0]...tab[n-1] */ +int binsearch (char *word, struct key tab[], int n); + +# endif diff --git a/chapter_6.structures/6_1.getword/getch.c b/chapter_6.structures/6_1.getword/getch.c new file mode 100644 index 0000000..394c9ee --- /dev/null +++ b/chapter_6.structures/6_1.getword/getch.c @@ -0,0 +1,25 @@ +# include + +# define BUFSIZE 128 + +int buf[BUFSIZE]; /* buffer for ungetch */ +int bufp = 0; /* next free position in buf */ + + +/* getch: get a (possibly pushed-back) character */ +int getch (void) +{ + return (bufp > 0) ? buf[--bufp] : getchar(); +} + + +/* ungetch: push character back on input */ +void ungetch (int c) +{ + if (bufp >= BUFSIZE) { + printf("ungetch: too many characters\n"); + } else { + buf[bufp++] = c; + } +} + diff --git a/chapter_6.structures/6_1.getword/getch.h b/chapter_6.structures/6_1.getword/getch.h new file mode 100644 index 0000000..fcf4e17 --- /dev/null +++ b/chapter_6.structures/6_1.getword/getch.h @@ -0,0 +1,9 @@ +# ifndef GETCH_H +# define GETCH_H + +/* getch: get a (possibly pushed-back) character */ +int getch (void); +/* ungetch: push character back on input */ +void ungetch (int c); + +# endif diff --git a/chapter_6.structures/6_1.getword/getword.c b/chapter_6.structures/6_1.getword/getword.c new file mode 100644 index 0000000..7eea9b5 --- /dev/null +++ b/chapter_6.structures/6_1.getword/getword.c @@ -0,0 +1,106 @@ +# include +# include +# include "getch.h" + +/* + Our version of getword does not properly handle underscores, string + constants, comments, or preprocessor control lines. Write a better version. +*/ + +int ignore_nonwords () +{ + int c = getch(); + + /* ignore white spaces */ + if (isspace(c)) { + while (isspace(c = getch())) + ; + ungetch(c); + return 1; + } + + /* ignore character constants */ + if (c == '\'') { + do { + if ((c = getch()) == '\\') { + getch(); + c = getch(); + } + } while (c != '\'' && c != EOF); + return 1; + } + + /* ignore string constants */ + if (c == '"') { + do { + if ((c = getch()) == '\\') { + getch(); + c = getch(); + } + } while (c != '"' && c != EOF); + return 1; + } + + /* ignore preprocessor commands */ + if (c == '#') { + while ((c = getch()) != EOF && c != '\n') + if ((c = getch()) == '\\') { + if ((c = getch()) == '\n') + c = getch(); + else + ungetch(c); + } + return 1; + } + + /* ignore comments */ + if (c == '/') { + if ((c = getch()) == '*') { + while (c != EOF) + if ((c = getch()) == '*') { + if ((c = getch()) == '/') + break; + else + ungetch(c); + } + return 1; + } + else + ungetch(c); + } + + /* ignore numbers */ + if (isdigit(c)) { + while (isdigit(c = getch()) || c == '.') + ; + ungetch(c); + return 1; + } + + ungetch(c); + return 0; +} + +/* getword: get next word or character from input */ +int getword (char *word, int lim) +{ + int c; + char *w = word; + + while (ignore_nonwords()) + ; + + if ((c = getch()) != EOF) + *w++ = c; + if (!isalpha(c) && c!='_') { + *w = '\0'; + return c; + } + for ( ; --lim > 0; w++) + if (!isalnum(*w = getch()) && *w!='_') { + ungetch(*w); + break; + } + *w = '\0'; + return word[0]; +} diff --git a/chapter_6.structures/6_1.getword/getword.h b/chapter_6.structures/6_1.getword/getword.h new file mode 100644 index 0000000..012cd7f --- /dev/null +++ b/chapter_6.structures/6_1.getword/getword.h @@ -0,0 +1,7 @@ +# ifndef GETWORD_H +# define GETWORD_H + +/* getword: get next word or character from input */ +int getword (char *word, int lim); + +# endif diff --git a/chapter_6.structures/6_1.getword/main.c b/chapter_6.structures/6_1.getword/main.c new file mode 100644 index 0000000..ba725b2 --- /dev/null +++ b/chapter_6.structures/6_1.getword/main.c @@ -0,0 +1,59 @@ +# include +# include +# include +# include "getword.h" +# include "binsearch.h" + +struct key keytab[] = { + {"auto", 0}, + {"break", 0}, + {"case", 0}, + {"char", 0}, + {"const", 0}, + {"continue", 0}, + {"default", 0}, + {"do", 0}, + {"double", 0}, + {"else", 0}, + {"enum", 0}, + {"extern", 0}, + {"float", 0}, + {"for", 0}, + {"goto", 0}, + {"if", 0}, + {"int", 0}, + {"long", 0}, + {"register", 0}, + {"return", 0}, + {"short", 0}, + {"signed", 0}, + {"sizeof", 0}, + {"static", 0}, + {"struct", 0}, + {"switch", 0}, + {"typedef", 0}, + {"union", 0}, + {"unsigned", 0}, + {"void", 0}, + {"volatile", 0}, + {"while", 0} +}; + +# define NKEYS (int)(sizeof keytab / sizeof(struct key)) +# define MAXWORD 128 + +/* count C keywords */ +int main () +{ + int n; + char word[MAXWORD]; + while (getword(word, MAXWORD) != EOF) + if (isalpha(word[0])) + if ((n = binsearch(word, keytab, NKEYS)) >= 0) + keytab[n].count++; + for (n = 0; n < NKEYS; n++) + if (keytab[n].count > 0) + printf("%4d %s\n", + keytab[n].count, keytab[n].word); + return 0; +} diff --git a/chapter_6.structures/6_1.getword/tests/0_getch.tin b/chapter_6.structures/6_1.getword/tests/0_getch.tin new file mode 100644 index 0000000..fcf4e17 --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/0_getch.tin @@ -0,0 +1,9 @@ +# ifndef GETCH_H +# define GETCH_H + +/* getch: get a (possibly pushed-back) character */ +int getch (void); +/* ungetch: push character back on input */ +void ungetch (int c); + +# endif diff --git a/chapter_6.structures/6_1.getword/tests/0_getch.tout b/chapter_6.structures/6_1.getword/tests/0_getch.tout new file mode 100644 index 0000000..415064e --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/0_getch.tout @@ -0,0 +1,2 @@ + 2 int + 2 void diff --git a/chapter_6.structures/6_1.getword/tests/1_main.tin b/chapter_6.structures/6_1.getword/tests/1_main.tin new file mode 100644 index 0000000..ba725b2 --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/1_main.tin @@ -0,0 +1,59 @@ +# include +# include +# include +# include "getword.h" +# include "binsearch.h" + +struct key keytab[] = { + {"auto", 0}, + {"break", 0}, + {"case", 0}, + {"char", 0}, + {"const", 0}, + {"continue", 0}, + {"default", 0}, + {"do", 0}, + {"double", 0}, + {"else", 0}, + {"enum", 0}, + {"extern", 0}, + {"float", 0}, + {"for", 0}, + {"goto", 0}, + {"if", 0}, + {"int", 0}, + {"long", 0}, + {"register", 0}, + {"return", 0}, + {"short", 0}, + {"signed", 0}, + {"sizeof", 0}, + {"static", 0}, + {"struct", 0}, + {"switch", 0}, + {"typedef", 0}, + {"union", 0}, + {"unsigned", 0}, + {"void", 0}, + {"volatile", 0}, + {"while", 0} +}; + +# define NKEYS (int)(sizeof keytab / sizeof(struct key)) +# define MAXWORD 128 + +/* count C keywords */ +int main () +{ + int n; + char word[MAXWORD]; + while (getword(word, MAXWORD) != EOF) + if (isalpha(word[0])) + if ((n = binsearch(word, keytab, NKEYS)) >= 0) + keytab[n].count++; + for (n = 0; n < NKEYS; n++) + if (keytab[n].count > 0) + printf("%4d %s\n", + keytab[n].count, keytab[n].word); + return 0; +} diff --git a/chapter_6.structures/6_1.getword/tests/1_main.tout b/chapter_6.structures/6_1.getword/tests/1_main.tout new file mode 100644 index 0000000..913fbb5 --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/1_main.tout @@ -0,0 +1,7 @@ + 1 char + 1 for + 3 if + 2 int + 1 return + 1 struct + 1 while diff --git a/chapter_6.structures/6_1.getword/tests/2_binsearch.tin b/chapter_6.structures/6_1.getword/tests/2_binsearch.tin new file mode 100644 index 0000000..207b7bd --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/2_binsearch.tin @@ -0,0 +1,21 @@ +# include +# include "binsearch.h" + +/* binsearch: find word in tab[0]...tab[n-1] */ +int binsearch (char *word, struct key tab[], int n) +{ + int cond; + int low, high, mid; + low = 0; + high = n - 1; + while (low <= high) { + mid = (low+high) / 2; + if ((cond = strcmp(word, tab[mid].word)) < 0) + high = mid - 1; + else if (cond > 0) + low = mid + 1; + else + return mid; + } + return -1; +} diff --git a/chapter_6.structures/6_1.getword/tests/2_binsearch.tout b/chapter_6.structures/6_1.getword/tests/2_binsearch.tout new file mode 100644 index 0000000..a58502f --- /dev/null +++ b/chapter_6.structures/6_1.getword/tests/2_binsearch.tout @@ -0,0 +1,7 @@ + 1 char + 2 else + 2 if + 4 int + 2 return + 1 struct + 1 while diff --git a/chapter_6.structures/Makefile b/chapter_6.structures/Makefile new file mode 100644 index 0000000..c58b272 --- /dev/null +++ b/chapter_6.structures/Makefile @@ -0,0 +1,3 @@ +SUBDIRS=$(wildcard 6_*/) + +include ../Chapter_incl.mk