treimplement max(1), mean(1), min(1), and sum(1) in C - numtools - perform nume… | |
git clone git://src.adamsgaard.dk/numtools | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit c0672a06ab06ee7def7d9acd6b728836f6de7397 | |
parent 5ef38a38146fe0d02f11b47687ea034699307c6f | |
Author: Anders Damsgaard <[email protected]> | |
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 | |
t@@ -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\ | |
t@@ -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 $< | |
t@@ -83,13 +88,14 @@ uninstall: | |
dist: | |
rm -rf "${NAME}-${VERSION}" | |
mkdir -p "${NAME}-${VERSION}" | |
- cp -rf ${MAN1} ${DOC} ${SRC} ${COMPATSRC} ${SCRIPTS} "${NAME}-${VERSIO… | |
+ 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 | |
t@@ -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 | |
t@@ -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",… | |
+ 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 | |
t@@ -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 | |
t@@ -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",… | |
+ 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 | |
t@@ -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 | |
t@@ -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",… | |
+ 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 | |
t@@ -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 | |
t@@ -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",… | |
+ 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 | |
t@@ -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 | |
t@@ -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 |