Plucking Out a Random Word

It’s time for your computer to babble nonsensically. No alcohol is necessary. All you must do is pluck out a random word from the dictionary. Run the program several times and you have babbly nonsense: subtotal spectacles lute's sushi's. Brilliant! *HIC*

From last week’s Lesson, you recall that the dictionary file contains a host of words, all in alphabetical order and (let’s hope) spelled correctly. Each word is stored on a line by itself. For this Lesson, the task is to grab a random word from the file.

I’ve worked with such random-grabbing programs before. On my Wambooli website, I have a “Zen moment” page that generates a random silly phrase each time the page is loaded or refreshed. It operates on the same principle as this week’s code: Obtain the number of lines in a file, generate a random value in that range, output the line number matching the value.

My Zen moment page is coded in PHP. The phrases are stored in an array. A single PHP function returns the array size, from which the random number is generated and the matching phrase output. For the Linux/Unix dictionary and C programming, you must read in the full file to count the number of words, generate a random number based on that value, then re-read the file to access the random word:

2023_10_28-Lesson.c

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

/* this code assumes the following path is valid */
#define DICTIONARY "/usr/share/dict/words"
#define SIZE 32

int main()
{
    FILE *dict;
    int wc,rw;
    char word[SIZE],*r;

    /* open the dictionary */
    dict = fopen(DICTIONARY,"r");
    if( dict==NULL )
    {
        fprintf(stderr,"Unable to open %s\n",DICTIONARY);
        exit(1);
    }

    /* read and tally the words */
    wc = 0;
    while( !feof(dict) )
    {
        r = fgets(word,SIZE,dict);    /* read a word */
        if( r==NULL )
            break;
        wc++;
    }

    /* pluck out a random word */
    rewind(dict);
    srand( (unsigned)time(NULL) );
    rw = rand() % wc;
    while(rw)
    {
        r = fgets(word,SIZE,dict);    /* read a word */
        rw--;
    }
    printf("%s",word);

    /* close */
    fclose(dict);

    return(0);
}

This code borrows a lot from previous lessons: The dictionary is opened. All entries are read and counted. The count value, stored in variable wc, is used with the rand() function to generate a random value within the word count range: rw = rand() % wc;

Before the random number is seeded and generated, something important must happen:

rewind(dict);

This statement returns the file position indicator to the start of the file. Otherwise, at this point in the code, the full file has already been read. The position indicator is at the EOF. When this statement is absent, the full list isn’t read again and the existing contents of the word[] buffer are output (the last word in the dictionary). Yes, I made this mistake and it took me a while to understand what happened.

The random value generated, rw, is used in a while loop to again read words from the dictionary. For each word read, rw is decremented. Eventually the value reaches zero and the given word, stored in the word[] array, is output.

Here is a sample run:

superabundances

If you were to construct a random (and meaningless) sentence, just re-read the file several times. Each time, remember to use the rewind() function to reset the file position indicator!

In next week’s Lesson I continue to play with the dictionary file.

Leave a Reply