读取包含单词的txt文件的行

时间:2017-05-06 13:53:48

标签: c

目前在学校,我正在开发一个类似街机的游戏项目。我有这个想法,每次我们进入下一个级别而不仅仅是“级别1”,“级别2”等时,在级别上放置一个随机名称... 所以我想知道如何使用fscanf或fgets或类似的东西做到这一点?我的文本文件包含70行不同的名称。

非常感谢:D

1 个答案:

答案 0 :(得分:0)

如果每行只有一个名字,那么请使用fgets()。

/******************************************************************************************
* This function reads a file line by line putting each line as a C-sting in an array
******************************************************************************************/
void read_names(char **names_table, int *n_names)
{
    FILE *fp = fopen(<filename>, "r");

    int i = 0;
    for(i = 0; i < MAX_N_NAMES; ++i){
        char *name = malloc(MAX_NAME_LENGTH);
        fgets(name, MAX_NAME_LENGTH, fp);

        if(name == NULL)
            break;

        name_table[i] = name;

    }

    *n_names = i; // There's a gotcha here

}

通过这种方式,你可以调用你的函数一次,然后我把它留给你来决定你的数组应该存在的位置(在内存中,谁拥有和管理它)。然后我会使用rand() % n_names为该级别选择该数组的随机索引。

在程序的某个地方,你应该有

enum NameParams { MAX_N_NAMES = 80, MAX_NAME_LENGTH = 20 }; (我比#define更喜欢这个,因为调试器会显示常量的名称。)

这应该让你开始,你可能想要做的一件事就是标记你使用的名称,以便不将它们用于两个级别。我会使用另一个int s数组(C没有bool)来标记所使用的级别。这有一个问题,你必须做rand()%n_names,直到你找到一个未使用的名字。

或者你可以将name_table洗牌一次,并将name_table [i]用于第i级。

void swap_indices(char **array, int i, int j) 
{
    char *tmp = array[i];
    array[i] = array[j];
    array[j] = tmp;
}

void shuffle(char **array, int length)
{
    // Do a bunch of swaps, depending on how much you care about randomness,
    // you might want to look up shuffling algorithms or see if some already
    // exist that you could use, but if you don't care that much, just
    // do a bunch of swaps.
}

最后,我建议使用一个独立的C文件(模块)来管理像这样的结构作为全局变量。您的.h文件可能如下所示(您将其包含在其他文件中,它将允许您访问模块的公共接口)。

#ifndef _LEVEL_NAMES_H_
#define _LEVEL_NAMES_H_

enum NameErrorCodes { ERR_NONE = 0, ERR_FILE, ERR_OTHER};
int names_init(char *filename);
char *get_name();

#endif

然后你的c文件看起来像这样:

#include "LevelNames.h"

struct LevelNames{
    int n_names;
    char * names[MAX_N_NAMES];
};

static struct LevelNames level_names; // static makes this global variable
                                      // accessible only from this file
                                      // It does the same thing for functions

static int read_names(char *filename);
static void swap_indices(char **array, int i, int j);
static void shuffle_names();

/*******************************************************************************
 *
*******************************************************************************/
int names_init(char *filename)
{
    int err = 0;
    err = read_names(filename);
    if( err != ERR_NONE )
        return err;
    shuffle_names();
}

/*******************************************************************************
 *
*******************************************************************************/
char *get_name(int level)
{
    if(level >= level_names.n_names || level < 0)
        return NULL;

    return level_names.names[i];
}

/*******************************************************************************
 * 
*******************************************************************************/
static int read_names(char *filename)
{
    FILE *fp = fopen(<filename>, "r");
    if( fp == NULL )
        return ERR_FILE;

    int i;
    for(i = 0; i < MAX_N_NAMES; ++i){
        char *name = malloc(MAX_NAME_LENGTH);
        fgets(name, MAX_NAME_LENGTH, fp);

        if(name == NULL)
            break;

        level_names.names[i] = name;

    }

    level_names. = i; // There's a gotcha here

    return ERR_NONE;
}

/*******************************************************************************
 *
*******************************************************************************/
static void swap_indices(char **array, int i, int j)
{
    ...
}

/*******************************************************************************
 *
*******************************************************************************/
static void shuffle_names()
{
    ...
}

这就是我要做的。并且不要忘记read_names中的那个陷阱。

我想以全局变量的讨论结束。你可能在学校被告知,你应该永远不要使用全局变量。这件事情是由很多原因导致的。他们是很好的理由,你应该听听那些对你这么说的人。

但是,我有一个模块,其唯一目的是管理一系列名称。因此,这个模块有一个全局变量是有道理的。此外,这个变量必须是静态的。这样,模块的客户端就不知道你的全局变量(他们不应该知道)。

C标准库的许多模块都有一个他们管理的静态全局变量。如果你想使用一个全局变量,因为你不知道应该如何从一个函数传递到另一个函数,那么弄清楚它并不使用全局变量。如果你想模仿C ++或Java中静态类的行为,那么这样做是合法的。