commit ce8461f31a92eb9a5988450303db8337a8864406
Author: phoebos <ben@bvnf.space>
Date: Mon, 21 Mar 2022 15:58:13 +0000
initial
Diffstat:
A | .gitignore | | | 1 | + |
A | Makefile | | | 6 | ++++++ |
A | freq.c | | | 123 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
3 files changed, 130 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+freq
diff --git a/Makefile b/Makefile
@@ -0,0 +1,6 @@
+.POSIX:
+
+XCFLAGS = $(CFLAGS) -Wall -Wextra -pedantic -Og -g -D_XOPEN_SOURCE=700
+
+freq: freq.c
+ $(CC) $(XCFLAGS) freq.c -o $@
diff --git a/freq.c b/freq.c
@@ -0,0 +1,123 @@
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+void freq(FILE *f, int field);
+
+struct count {
+ char *name;
+ int freq;
+};
+
+struct count *cs;
+size_t cs_len = 0;
+
+size_t
+get_index(char *name) {
+ for (size_t i = 0; i < cs_len; i++) {
+ if (strcmp(cs[i].name, name) == 0)
+ return i;
+ }
+ return -1;
+}
+
+/* can only increase freqs */
+void
+update_record(char *name) {
+ int i = get_index(name);
+ if (i == -1) {
+ /* create record */
+ cs_len++;
+ cs = realloc(cs, sizeof(struct count) * cs_len);
+ if (cs == NULL) {
+ perror("realloc");
+ exit(1);
+ }
+ cs[cs_len - 1].name = strdup(name);
+ cs[cs_len - 1].name = 0;
+ } else {
+ /* add 1 to freq */
+ cs[i].freq++;
+ }
+}
+
+void
+print_freqs(void) {
+ for (size_t i = 0; i < cs_len; i++)
+ printf("%d %s\n", cs[i].freq, cs[i].name);
+}
+
+int
+main (int argc, char **argv) {
+ int c, field = 0;
+ while ((c = getopt(argc, argv, ":k:")) != -1) {
+ switch (c) {
+ case 'k':
+ field = atoi(optarg);
+ break;
+ case '?':
+ fprintf(stderr, "usage: %s [-k fieldnum] [file]\n", argv[0]);
+ return 1;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ FILE *f = stdin;
+ if (*argv) {
+ if (strcmp(*argv, "-") != 0) {
+ f = fopen(*argv, "r");
+ if (f == NULL) {
+ perror(*argv);
+ return 1;
+ }
+ }
+ }
+
+ freq(f, field);
+
+ if (f != stdin)
+ fclose(f);
+ return 0;
+}
+
+void
+freq(FILE *f, int field) {
+ char *line = NULL;
+ size_t linelen = 0;
+ ssize_t n;
+ int cur_field = 1;
+ int in_word = 0;
+
+ while ((n = getline(&line, &linelen, f)) != -1) {
+ ssize_t i = 0;
+ char *field_start = line;
+ /* eat up whitespace at front */
+ while (isspace(line[i++]));
+ for (; i < n; i++) {
+ if (isspace(line[i])) {
+ if (in_word) {
+ if (cur_field == field) {
+ line[i] = '\0';
+ goto field_found;
+ }
+ cur_field++;
+ in_word = 0;
+ }
+ } else {
+ if (!in_word)
+ field_start = line + i;
+ in_word = 1;
+ }
+ }
+field_found:
+ fprintf(stderr, "found '%s'\n", field_start);
+ update_record(field_start);
+
+ }
+ free(line);
+
+ print_freqs();
+}