commit c0672a06ab06ee7def7d9acd6b728836f6de7397
parent 5ef38a38146fe0d02f11b47687ea034699307c6f
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Tue, 31 Aug 2021 14:39:37 +0200
reimplement max(1), mean(1), min(1), and sum(1) in C
Diffstat:
M | Makefile | | | 30 | ++++++++++++++++++------------ |
D | max | | | 14 | -------------- |
A | max.c | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
D | mean | | | 13 | ------------- |
A | mean.c | | | 41 | +++++++++++++++++++++++++++++++++++++++++ |
D | min | | | 14 | -------------- |
A | min.c | | | 38 | ++++++++++++++++++++++++++++++++++++++ |
D | sum | | | 13 | ------------- |
A | sum.c | | | 39 | +++++++++++++++++++++++++++++++++++++++ |
A | util.c | | | 47 | +++++++++++++++++++++++++++++++++++++++++++++++ |
M | util.h | | | 4 | ++++ |
11 files changed, 225 insertions(+), 66 deletions(-)
diff --git a/Makefile b/Makefile
@@ -8,18 +8,19 @@ PREFIX = /usr/local
MANPREFIX = ${PREFIX}/man
DOCPREFIX = ${PREFIX}/share/doc/${NAME}
-SCRIPTS =\
- histpdf\
+BIN =\
max\
mean\
min\
+ rangetest\
sum\
- transpose\
-BIN =\
- rangetest\
+SCRIPTS =\
+ histpdf\
+ transpose\
-SRC = ${BIN:=.c}
+SRC =\
+ util.c
COMPATSRC =\
strnlen.c\
@@ -45,14 +46,18 @@ DOC =\
all: ${BIN}
-${BIN}: ${LIB} ${@:=.o}
-
OBJ = ${SRC:.c=.o} ${COMPATOBJ}
${OBJ}: ${HDR}
-.o:
- ${CC} -o $@ $< ${_LDFLAGS} ${LIB}
+max: max.o
+mean: mean.o
+min: min.o
+rangetest: rangetest.o
+sum: sum.o
+
+${BIN}: ${LIB} ${OBJ}
+ ${CC} ${_LDFLAGS} -o $@ ${@:=.o} ${OBJ}
.c.o:
${CC} ${_CFLAGS} ${_CPPFLAGS} -o $@ -c $<
@@ -83,13 +88,14 @@ uninstall:
dist:
rm -rf "${NAME}-${VERSION}"
mkdir -p "${NAME}-${VERSION}"
- cp -rf ${MAN1} ${DOC} ${SRC} ${COMPATSRC} ${SCRIPTS} "${NAME}-${VERSION}"
+ cp -rf ${MAN1} ${DOC} ${BIN:=.c} ${SRC} ${COMPATSRC} ${SCRIPTS} \
+ Makefile "${NAME}-${VERSION}"
# make tarball
tar cf - "${NAME}-${VERSION}" | \
gzip -c > "${NAME}-${VERSION}.tar.gz"
rm -rf "${NAME}-${VERSION}"
clean:
- rm -f ${BIN} ${OBJ} ${LIB}
+ rm -f ${BIN} ${BIN:=.o} ${OBJ} ${LIB}
.PHONY: install uninstall dist clean
diff --git a/max b/max
@@ -1,14 +0,0 @@
-#!/usr/bin/awk -f
-{
- for (i = 1; i <= NF; i++)
- if (NR == 1 || $i > max[i])
- max[i] = $i
-}
-END {
- for (i = 1; i <= NF; i++) {
- printf("%g", max[i])
- if (i < NF)
- printf("\t")
- }
- printf("\n")
-}
diff --git a/max.c b/max.c
@@ -0,0 +1,38 @@
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int
+main(void)
+{
+ size_t i = 0, nf = 0, nr = 0, linesize = 0;
+ char *line = NULL, *data = NULL;
+ double val, *vals = NULL;
+ int offset;
+
+ if (pledge("stdio", NULL) == -1)
+ err(2, "pledge");
+
+ while (getline(&line, &linesize, stdin) > 0) {
+ if (nr == 0)
+ if ((nf = allocarr(&vals, line, linesize)) == 0)
+ errx(1, "no fields in input");
+ data = line;
+ for (i = 0; i < nf; i++) {
+ if (!scannextval(&data, &val))
+ errx(1, "could not parse line %ld, field %ld", nr + 1, i + 1);
+ if (nr == 0 || val > vals[i])
+ vals[i] = val;
+ }
+ nr++;
+ }
+ printarr(vals, nf);
+
+ free(line);
+ free(vals);
+
+ return 0;
+}
diff --git a/mean b/mean
@@ -1,13 +0,0 @@
-#!/usr/bin/awk -f
-{
- for (i = 1; i <= NF; i++)
- sum[i] += $i
-}
-END {
- for (i = 1; i <= NF; i++) {
- printf("%g", sum[i] / NR)
- if (i < NF)
- printf("\t")
- }
- printf("\n")
-}
diff --git a/mean.c b/mean.c
@@ -0,0 +1,41 @@
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int
+main(void)
+{
+ size_t i = 0, nf = 0, nr = 0, linesize = 0;
+ char *line = NULL, *data = NULL;
+ double val, *vals = NULL;
+ int offset;
+
+ if (pledge("stdio", NULL) == -1)
+ err(2, "pledge");
+
+ while (getline(&line, &linesize, stdin) > 0) {
+ if (nr == 0)
+ if ((nf = allocarr(&vals, line, linesize)) == 0)
+ errx(1, "no fields in input");
+ data = line;
+ for (i = 0; i < nf; i++) {
+ if (!scannextval(&data, &val))
+ errx(1, "could not parse line %ld, field %ld", nr + 1, i + 1);
+ if (nr == 0)
+ vals[i] = 0.0;
+ vals[i] += val;
+ }
+ nr++;
+ }
+ for (i = 0; i < nf; i++)
+ vals[i] /= (double)nr;
+ printarr(vals, nf);
+
+ free(line);
+ free(vals);
+
+ return 0;
+}
diff --git a/min b/min
@@ -1,14 +0,0 @@
-#!/usr/bin/awk -f
-{
- for (i = 1; i <= NF; i++)
- if (NR == 1 || $i < min[i])
- min[i] = $i
-}
-END {
- for (i = 1; i <= NF; i++) {
- printf("%g", min[i])
- if (i < NF)
- printf("\t")
- }
- printf("\n")
-}
diff --git a/min.c b/min.c
@@ -0,0 +1,38 @@
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int
+main(void)
+{
+ size_t i = 0, nf = 0, nr = 0, linesize = 0;
+ char *line = NULL, *data = NULL;
+ double val, *vals = NULL;
+ int offset;
+
+ if (pledge("stdio", NULL) == -1)
+ err(2, "pledge");
+
+ while (getline(&line, &linesize, stdin) > 0) {
+ if (nr == 0)
+ if ((nf = allocarr(&vals, line, linesize)) == 0)
+ errx(1, "no fields in input");
+ data = line;
+ for (i = 0; i < nf; i++) {
+ if (!scannextval(&data, &val))
+ errx(1, "could not parse line %ld, field %ld", nr + 1, i + 1);
+ if (nr == 0 || val < vals[i])
+ vals[i] = val;
+ }
+ nr++;
+ }
+ printarr(vals, nf);
+
+ free(line);
+ free(vals);
+
+ return 0;
+}
diff --git a/sum b/sum
@@ -1,13 +0,0 @@
-#!/usr/bin/awk -f
-{
- for (i = 1; i <= NF; i++)
- sum[i] += $i
-}
-END {
- for (i = 1; i <= NF; i++) {
- printf("%g", sum[i])
- if (i < NF)
- printf("\t")
- }
- printf("\n")
-}
diff --git a/sum.c b/sum.c
@@ -0,0 +1,39 @@
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "util.h"
+
+int
+main(void)
+{
+ size_t i = 0, nf = 0, nr = 0, linesize = 0;
+ char *line = NULL, *data = NULL;
+ double val, *vals = NULL;
+ int offset;
+
+ if (pledge("stdio", NULL) == -1)
+ err(2, "pledge");
+
+ while (getline(&line, &linesize, stdin) > 0) {
+ if (nr == 0)
+ if ((nf = allocarr(&vals, line, linesize)) == 0)
+ errx(1, "no fields in input");
+ data = line;
+ for (i = 0; i < nf; i++) {
+ if (!scannextval(&data, &val))
+ errx(1, "could not parse line %ld, field %ld", nr + 1, i + 1);
+ if (nr == 0)
+ vals[i] = 0.0;
+ vals[i] += val;
+ }
+ nr++;
+ }
+ printarr(vals, nf);
+
+ free(line);
+ free(vals);
+
+ return 0;
+}
diff --git a/util.c b/util.c
@@ -0,0 +1,47 @@
+#include <err.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DELIM '\t'
+#define DELIMSTR "\t"
+
+size_t
+allocarr(double **arr, const char *str, size_t maxlen)
+{
+ size_t i, nf = 0;
+
+ if (maxlen > 0)
+ nf = 1;
+ for (i = 0; i < maxlen && str[i] != '\0'; i++)
+ if (str[i] == DELIM)
+ nf++;
+ if (!(*arr = calloc(nf, sizeof(double))))
+ err(1, "calloc");
+
+ return nf;
+}
+
+int
+scannextval(char **str, double *val)
+{
+ int offset;
+
+ if (sscanf(*str, "%lg%n", val, &offset) != 1)
+ return 0;
+ *str += offset;
+
+ return 1;
+}
+
+void
+printarr(double *arr, size_t len)
+{
+ size_t i;
+
+ for (i = 0; i < len; i++) {
+ printf("%g", arr[i]);
+ if (i < len)
+ printf(DELIMSTR);
+ }
+ puts("");
+}
diff --git a/util.h b/util.h
@@ -14,4 +14,8 @@ size_t strlcpy(char *dst, const char *src, size_t dsize);
#undef strnlen
size_t strnlen(const char *str, size_t maxlen);
+size_t allocarr(double **arr, const char *str, size_t maxlen);
+int scannextval(char **str, double *val);
+void printarr(double *arr, size_t len);
+
#endif