【问题标题】:How to Read and Return Random Line From Txt(C)如何从 Txt(C) 读取和返回随机行
【发布时间】:2020-07-30 10:11:17
【问题描述】:

文本每行包含 100 个单词,1 个单词最多 20 个字符在代码下方打印相同的内容,我想要这个随机的,如何编辑我的代码? 两个 printf 函数打印同一个单词。 我浏览了所有相关的主题,但我没有开悟,因为我是一个新学习者。

int main(){
char *str;
char *str_2;
    printf("%s",word("words.txt",str));
    printf("%s",word("words.txt",str_2));
}


char *word(char *file, char *str0) {
    int end, loop, line;
    int i;


   str0 = (char *)malloc(20);

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

    if (fd == NULL) {
        printf("Failed to open file\n");
        return (NULL);
    }

    srand(time(NULL));
    line = rand() % 100 + 1;

    for (end = loop = 0; loop < line; ++loop) {
        if (NULL == fgets(str0, 20, fd)) {
            end = 1;
            break;
        }
    }

    if (!end){
            fclose(fd);

            return str0;
            free(str0);

    }
}

【问题讨论】:

    标签: c string file pointers random


    【解决方案1】:

    有许多错误和一些改进。

    这是您的代码的注释版本,其中显示了错误以及潜在的更改和修复:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    char *
    word(char *file, char *str0)
    {
        int end, loop, line;
    #if 0
        int i;
    #endif
    
    // NOTE/BUG: don't cast the return of malloc
    #if 0
        str0 = (char *) malloc(20);
    #else
        str0 = malloc(20);
    #endif
    
        FILE *fd = fopen(file, "r");
    
    // NOTE/BUG: opening and closing the file on _each_ call is wasteful -- having
    // main open the file and passing the file descriptor is faster
        if (fd == NULL) {
            printf("Failed to open file\n");
            return (NULL);
        }
    
        // NOTE/BUG: put this in main
    #if 0
        srand(time(NULL));
    #endif
        line = rand() % 100 + 1;
    
        for (end = loop = 0; loop < line; ++loop) {
            if (NULL == fgets(str0, 20, fd)) {
                end = 1;
                break;
            }
        }
    
    #if 1
        fclose(fd);
    #endif
    
        if (!end) {
    // NOTE/BUG: the fclose should _always_ be done (even on EOF) -- put it above
    #if 0
            fclose(fd);
    #endif
    
            return str0;
    // NOTE/BUG: this will _never_ be executed -- so the return will leak this
    // memory -- put free in main
    #if 0
            free(str0);
    #endif
        }
    
    // NOTE/BUG: on EOF, we fall through to here -- we have no return statement
    // for this case
    #if 1
        return str0;
    #endif
    }
    
    int
    main(void)
    {
        char *str;
        char *str_2;
    
    #if 1
        srand(time(NULL));
    #endif
    // NOTE/BUG: passing the 2nd argument does nothing because word will toss any
    // value
    // NOTE/BUG: str and str_2 are _uninitialized
        printf("%s", word("words.txt", str));
        printf("%s", word("words.txt", str_2));
    
    // NOTE/BUG: no return for main
    #if 1
        return 0;
    #endif
    }
    

    这是一个清理后的工作版本:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    char *
    word(FILE *fd)
    {
        char *str0;
        int end, loop, line;
        int len;
    
        len = 20;
        str0 = malloc(len);
    
        line = rand() % 100 + 1;
    
        rewind(fd);
    
        end = 0;
        for (loop = 0; loop < line; ++loop) {
            if (NULL == fgets(str0, len, fd)) {
                end = 1;
                break;
            }
        }
    
        if (end) {
            free(str0);
            str0 = NULL;
        }
    
        return str0;
    }
    
    int
    main(void)
    {
        char *str;
    
        srand(time(NULL));
    
        char *file = "words.txt";
        FILE *fd = fopen(file, "r");
    
        if (fd == NULL) {
            printf("Failed to open file\n");
            return 1;
        }
    
        for (int i = 1;  i <= 20;  ++i) {
            str = word(fd);
            if (str == NULL)
                continue;
    
            printf("%d: %s", i, str);
    
            free(str);
        }
    
        fclose(fd);
    
        return 0;
    }
    

    word 中执行malloc 可能是一种浪费。如果您打算让调用者将所有字符串保存在一个数组中,这并不是绝对错误的。

    很多时候,对于像word 这样的函数,调用者可以将缓冲区指针及其最大长度作为参数传递下来。这使得word 更类似于fgets

    这是一个这样做的版本,以说明另一种方法:

    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    int
    word(FILE *fd,char *str0,int len)
    {
        int found, loop, line;
    
        line = rand() % 100 + 1;
    
        rewind(fd);
    
        found = 1;
        for (loop = 0; loop < line; ++loop) {
            if (NULL == fgets(str0, len, fd)) {
                found = 0;
                break;
            }
        }
    
        return found;
    }
    
    int
    main(void)
    {
        char *str;
        int len = 20;
    
        srand(time(NULL));
    
        char *file = "words.txt";
        FILE *fd = fopen(file, "r");
    
        if (fd == NULL) {
            printf("Failed to open file\n");
            return 1;
        }
    
        str = malloc(len);
    
        for (int i = 1;  i <= 20;  ++i) {
            if (! word(fd,str,len))
                continue;
    
            printf("%d: %s", i, str);
        }
    
        fclose(fd);
        free(str);
    
        return 0;
    }
    

    【讨论】:

    • 非常感谢,您的修改对我的学习很有帮助
    猜你喜欢
    • 1970-01-01
    • 2017-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多