如果文件的每一行包含一个单词,一种可能性是打开文件并首先计算行数。然后rewind()文件流,在文件字数范围内选择一个随机数sel。接下来,在循环中调用fgets() 将sel 字读入缓冲区。读取的最后一个单词可以复制到存储结果的数组中。倒带并重复所需的每个单词。
这是一个使用 Linux 系统上典型的 /usr/share/dict/words 文件的程序。请注意,如果文件中的行数大于RAND_MAX(rand() 可以返回的最大行数),则行号较大的单词将被忽略。这个数字可以小到 32767。在 GNU C 库中,RAND_MAX 是 2147483647。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define MAX_WORD 100
#define NUM_WORDS 10
int main(void)
{
/* Open words file */
FILE *fp = fopen("/usr/share/dict/words", "r");
if (fp == NULL) {
perror("Unable to locate word list");
exit(EXIT_FAILURE);
}
/* Count words in file */
char word[MAX_WORD];
long wc = 0;
while (fgets(word, sizeof word, fp) != NULL) {
++wc;
}
/* Store random words in array */
char randwords[NUM_WORDS][MAX_WORD];
srand((unsigned) time(NULL));
for (size_t i = 0; i < NUM_WORDS; i++) {
rewind(fp);
int sel = rand() % wc + 1;
for (int j = 0; j < sel; j++) {
if (fgets(word, sizeof word, fp) == NULL) {
perror("Error in fgets()");
}
}
strcpy(randwords[i], word);
}
if (fclose(fp) != 0) {
perror("Unable to close file");
}
/* Display results */
for (size_t i = 0; i < NUM_WORDS; i++) {
printf("%s", randwords[i]);
}
return 0;
}
程序输出:
biology's
lists
revamping
slitter
loftiness's
concur
solemnity's
memories
winch's
boosting
如果输入中的空行是一个问题,选择循环可以测试它们并在它们出现时重置以选择另一个单词:
/* Store random words in array */
char randwords[NUM_WORDS][MAX_WORD];
srand((unsigned) time(NULL));
for (size_t i = 0; i < NUM_WORDS; i++) {
rewind(fp);
int sel = rand() % wc + 1;
for (int j = 0; j < sel; j++) {
if (fgets(word, sizeof word, fp) == NULL) {
perror("Error in fgets()");
}
}
if (word[0] == '\n') { // if line is blank
--i; // reset counter
continue; // and select another one
}
strcpy(randwords[i], word);
}
请注意,如果文件包含仅个空行,则通过上述修改,程序将永远循环;计算一行中选择的空白行数并跳过直到达到某个合理的阈值可能更安全。最好在初始行数期间验证输入文件的至少一行不是空白:
/* Count words in file */
char word[MAX_WORD];
long wc = 0;
long nonblanks = 0;
while (fgets(word, sizeof word, fp) != NULL) {
++wc;
if (word[0] != '\n') {
++nonblanks;
}
}
if (nonblanks == 0) {
fprintf(stderr, "Input file contains only blank lines\n");
exit(EXIT_FAILURE);
}