【问题标题】:How can I read in a random string from a large list of words in C?如何从 C 中的大量单词中读取随机字符串?
【发布时间】:2017-03-17 16:23:46
【问题描述】:

我正在开发游戏刽子手的基本实现。

我有一个包含最多 1000 个常用英语单词的文本文件,我想随机选择其中一个作为我游戏中的单词。

我知道我需要在我的程序中使用 fopen 和 fscanf 将单词转换为字符串,但是如何选择读取哪个字符串?

我是否必须将整个列表导入一个数组,然后从中选择一个?或者有什么方法可以让我只选择要扫描的单词?

【问题讨论】:

  • 您是否尝试过使用 rand() 函数生成 1 到 1000 之间的数字?
  • 看到这个question。

标签: c file io scanf stdio


【解决方案1】:

您不需要只需将所有单词读入程序即可选择一个。

您可以改为寻找单词文件中的一个随机点,一直移动直到看到换行符(或任何分隔单词),使用fgets() 或scanf() 读入一个单词并关闭文件:

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

void random_word(const char *file_name, char *buffer, size_t length) {

    FILE *file = fopen(file_name, "r");

    if (file == NULL) {
        fprintf(stderr, "Can't open %s!\n", file_name);
        exit(EXIT_FAILURE);
    }

    (void) fseek(file, 0L, SEEK_END);
    long size = ftell(file);

    int c = EOF;

    while (c == EOF || fgets(buffer, length, file) == NULL) {
        long offset = random() % size;

        (void) fseek(file, offset, SEEK_SET);

        while ((c = getc(file)) != EOF && c != '\n');
    }

    buffer[strlen(buffer) - 1] = '\0'; // remove trailing \n

    (void) fclose(file);
}


int main() {

    srandom(time(NULL));

    char buffer[1024];

    for (int i = 0; i < 10; i++) {
        random_word("/usr/share/dict/words", buffer, sizeof(buffer));

        (void) puts(buffer);
    }

    return 0;
}

示例

> ./a.out
boloman
disentrance
guanase
decorable
snibbled
redemandable
Cluniac
balneal
turbidimetry
catechistically
> 

此代码不需要复杂或高效,因为它是一个罕见的事件,处理方面,您选择一个新单词并且它发生在人工时间范围内,而不是高速处理时间范围内。

【讨论】:

  • 这种方法不支持更长的单词吗?并不是说这对刽子手来说一定是个问题。
  • 我刚刚尝试实现这个,似乎当我运行它时,它连续两次返回相同的单词,然后改变;而不是每次都换一个词。
  • 已修复问题 - Num Gen 是基于时间的,在太短的时间内读取两个读数会给出相同的索引。
  • @Lewiky,完全正确。这只是一个种子问题。如果您的程序连续要求十个随机单词,它会正常工作。但是,如果您调用我的示例太快,它会在同一时间重新播种并产生相同的单词。只是示例的工件,不是真正的问题。
  • @DavidBowling,你能解释一下这种偏见吗?在我看来,它有更大的机会随机落在一个长单词的中间(它忽略并移动过去),然后返回下一个单词。你说长词比短词更可能跟随长词吗?
【解决方案2】:

简单的方法是放入一个数组,然后得到一个随机索引。 更复杂但高效的是读取每个单词的索引,保存到另一个文件,然后,只需读取存储该单词的扇区。 真的,只要把它放在一个数组中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    相关资源
    最近更新 更多