wc_clone.c in C
A word-count clone: read named files or stdin, count lines, words and bytes.
#include <ctype.h>
#include <stdio.h>
typedef struct {
long lines;
long words;
long bytes;
} Counts;
static Counts count_stream(FILE *f) {
Counts c = {0, 0, 0};
int in_word = 0;
int ch;
while ((ch = fgetc(f)) != EOF) {
c.bytes++;
if (ch == '\n') {
c.lines++;
}
if (isspace(ch)) {
in_word = 0;
} else if (!in_word) {
in_word = 1;
c.words++;
}
}
return c;
}
static void print_counts(Counts c, const char *label) {
printf("%8ld %8ld %8ld %s\n", c.lines, c.words, c.bytes, label);
}
int main(int argc, char **argv) {
if (argc < 2) {
print_counts(count_stream(stdin), "-");
return 0;
}
Counts total = {0, 0, 0};
int failures = 0;
for (int i = 1; i < argc; i++) {
FILE *f = fopen(argv[i], "rb");
if (f == NULL) {
fprintf(stderr, "cannot open %s\n", argv[i]);
failures++;
continue;
}
Counts c = count_stream(f);
if (ferror(f)) {
fprintf(stderr, "error reading %s\n", argv[i]);
failures++;
}
fclose(f);
print_counts(c, argv[i]);
total.lines += c.lines;
total.words += c.words;
total.bytes += c.bytes;
}
if (argc > 2) {
print_counts(total, "total");
}
return failures > 0;
}
How it works
- Each file is counted by one pass over its characters.
- With no arguments it falls back to reading stdin.
- A totals line prints when more than one file was given.
Keywords and builtins used here
FILENULLcharconstcontinuecount_streamelseforifintlongmainprint_countsreturnstaticstructtypedefvoidwhile
The run, in numbers
- Lines
- 67
- Characters to type
- 1075
- Tokens
- 374
- Three-star pace
- 105 tpm
At the three-star pace of 105 tokens a minute, this run takes about 214 seconds.
Step 1 of 1 in Encore, step 12 of 12 in Files & I/O.