【问题标题】:C Random, having problemsC 随机,有问题
【发布时间】:2012-09-16 13:33:26
【问题描述】:
void getS(char *fileName){
    FILE *src;
    if((src = fopen(fileName, "r")) == NULL){
        printf("%s %s %s", "Cannot open file ", fileName, ". The program is now ending.");
        exit(-1);
    }
    //char *get = " ";      

    int c = 1;
    char ch = 'x';
    while(ch!=EOF) {
        ch = fgetc(src);
        if(ch == '\n')  c++;
    }
    fseek(src, 0, SEEK_SET);
    int random = rand() % c;
    int i = 0;
    for(i = 0; i < random; i++){
        while(ch != '\n'){
            ch = fgetc(src);
        }
    }
    do{
        ch = fgetc(src);
        if(ch != '\n' && ch != EOF){
            printf("%c", ch);
        }
    }while(ch != '\n' && ch != EOF);
    printf("%c", '\n');
    fclose(src);
}

所以这是我的函数,它抓取一个文件并打印出文件中的一个随机单词,如果每个单词由一个新行分隔。

问题 1: 为什么随机的会偏爱前两个词?

问题 2:我将如何制作它以便我可以多次使用此功能而无需执行 printf("%c", '\n');因为如果我最后没有那个,之前的函数调用只会覆盖旧的。

在此先感谢,我今天一直在问一些问题,感谢 stackoverflow 的所有帮助! :)

附:使用 srand(time(NULL));

【问题讨论】:

  • % 运算符总是有一些偏差,除非可能的随机值的数量完全可整除,尽管这可能不是一个重要问题。但是,有一个巧妙的技巧可以避免需要两次通过文件。当您找到第一个单词时,您有 100% 的机会选择它。当您找到第二个单词时,您有二分之一的机会选择它。当您找到第三个单词时,您有三分之一的机会选择它,依此类推。您需要生成大量随机数,但这通常比两次遍历文件要便宜。
  • 您可能需要仔细检查概率才能对此感到满意,但是是的,它确实会选择最后概率相等的任何单词。最近有一篇博文提到了这一点,但我失去了链接。
  • 你可以用putchar(ch)代替printf("%c", ch)...这样更清晰更快捷。

标签: c function text methods random


【解决方案1】:

看这里的逻辑:

    for(i = 0; i < random; i++){
        while(ch != '\n'){
            ch = fgetc(src);
        }
    }

点击换行后,您将不再阅读任何字符,因此您总是要打印第一行或第二行。

你可以这样修复它:

    for(i = 0; i < random; i++){
        ch = fgetc(src); // start by reading the first character on the line
        while(ch != '\n'){
            ch = fgetc(src);
        }
    }

Jim Balter 还指出,最好将 ch 声明为 int。这是因为 EOF 不被视为常规字符。

【讨论】:

  • 我对回车到底是什么感到困惑。是'\r'吗?究竟是怎么引起的?
  • 哦,我想我明白了,但我怎么会不读回车,所以它不会在文件开头重新启动我?
  • @OstapHnatyuk:我不知道你的意思是“所以它不会让我回到文件的开头”。只有 fseek() 会导致它从文件的开头重新开始。
  • 啊,好吧,我明白了。是的,它有效!您是否也知道如何解决问题 2?我必须在新行上打印所有这些单词,否则它们只会相互删除。
  • 是的,我现在了解 '\r' 的交互方式。对这种误解深表歉意。
【解决方案2】:

最后没有printf("%c","\n"); 行,它工作正常......

【讨论】:

    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 2012-04-13
    • 2011-05-21
    • 2012-06-16
    • 2017-04-10
    • 1970-01-01
    • 2011-05-18
    • 1970-01-01
    相关资源
    最近更新 更多