freq

unnamed repository
Log | Files | Refs

commit ce8461f31a92eb9a5988450303db8337a8864406
Author: phoebos <ben@bvnf.space>
Date:   Mon, 21 Mar 2022 15:58:13 +0000

initial

Diffstat:
A.gitignore | 1+
AMakefile | 6++++++
Afreq.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(); +}