My goal is to go through the list of all English words (separated by '\n'
characters) and find the longest word which doesn't have any of these characters: "gkmqvwxz"
. And I want to optimize it as much as possible. Here's what I came up with:
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <unistd.h>
static inline int is_legal(size_t beg, size_t end, char* buffer)
{
static const char* bad = "gkmqvwxzio"; /* unwanted chars */
for (; beg != end; ++beg) { /* go through current word */
char ch = tolower(buffer[beg]); /* The char might be upper case */
for (size_t j = 0; bad[j]; ++j)
if (ch == bad[j]) /* If it is found, return false */
return 0;
}
return 1; /* else return true */
}
int main(void)
{
char *buffer = NULL; /* contents of the text file */
size_t length = 5000000; /* maximum size */
FILE* fp;
fp = fopen("words.txt", "rb");
if (fp) {
fseek(fp, 0, SEEK_END);
fseek(fp, 0, SEEK_SET);
buffer = malloc(length);
if (buffer) {
fread(buffer, 1, length, fp); /* read it all */
}
fclose(fp);
}
size_t beg = 0; /* current word boundaries */
size_t end = 0;
size_t mbeg = 0; /* result word */
size_t mend = 0;
while (buffer[end]) {
beg = end++;
for (; buffer[end] && buffer[end] != '\n'; ++end) /* read the next word */
; /* for loop doesn't have a body */
if ((end - beg) > (mend - mbeg) && is_legal(beg, end, buffer)) { /* if it is a fit, save it */
mbeg = beg;
mend = end;
}
}
printf("%.*s\n", mend - mbeg, buffer + mbeg); /* print the output */
return 0;
}
I read it all at once, then go through it with two indexes denoting beginning and ending of current word. When I find a word that fits, I save the corresponding indexes. Finally I print the output, which is "supertranscendentness"
. The output is correct, but I'd like to know:
- If there's undefined behavior in my code
- If there's a better way of doing this (without sacrificing performance)
- If there's a way to improve the performance
Another point is the size_t length = 5000000;
part. It is an estimated size of the string based of the file size.