动态fscanf成阵列

问题描述 投票:0回答:1

我试图将一些文本放入我的数组的结构部分是一个数组,它接受部分文本。

例如,我的结构是:

struct animal
{
    char animal_Type[11];
    int age;
    int numberOfLegs;
    int walksPerDay;
    char favoriteFood[];
};

然后我会输入如下:

dog,2,4,2,biscuits,wet
cat,5,4,0,biscuits,wet,dry,whiskers
bird,1,2,0,birdseed,biscuits,bread,oats,worms,insects,crackers

我有一个可行的解决方案,每天将所有值放到结构中,但我希望能够将食物放入最喜欢的食物中。我有一个动态数组,但我不知道如何将剩余的文本读入favoriteFood数组。

使用的代码是:

fp = open("animals.txt","r");
struct animal *animal = malloc(sizeof(sturct animal)*3);
int i = 0;
if(fp != NULL) {
     while(i < 3) {
fscanf(fp,"%s %d %d %d %s",
     animal[i].animal_Type,
     animal[i].age,
     animal[i].numberOfLegs,
     animal[i].walksPerDay,
     animal[i].favoriteFood); // need to be able to enter the string of food into here
i++
}

我该怎么做呢?

c file input scanf
1个回答
0
投票

首先,你的struct与你在评论中所说的不一致。

char favoriteFood[];

上面是char的数组,因此除了它是一个字符串之外,不可能有一份喜欢的食物清单。由于数组的大小未指定,因此您无法像之前那样填充它。相反,你真正想要的是

char **favoriteFood;
unsigned int favoriteFoodSize;

这将允许您创建一个扩展的字符串列表,以适应您需要容纳的任何数据。

至于阅读它,最好的方法是使用fgets读取整行,然后使用类似strtok的东西来破坏你的分隔符。首先定义一个非常大的字符串来保存整行,并使用char *来保存每个字段。

char buffer[1024];
char *token;

然后到主循环将是这样的:

while(fgets(buffer,1024,fp)) {
    token=strtok(buffer,",");
    strcpy(beasts[i].animal_Type,token);

    token=strtok(NULL,",");
    beasts[i].age = atoi(token);

    /* etc... */
}

你需要检查token是否曾经NULL来应对短线的可能性并相应地处理它。并确保复制到animal_Type的字符串不超过10个字符...或替代使它成为char *所以你可以有任何大小的字符串。

对于favoriteFood,您需要使用realloc来增加它的大小以适应添加的每种新食物并继续通过该字符串直到您用完代币。

token=strtok(NULL,",");
if(token) {
    beasts[i].favoriteFood=malloc(sizeof(char *));
    beasts[i].favoriteFood[0]=strdup(token); // Need to index using 0 as favoriteFoodSize won't have a value yet
    beasts[i].favoriteFoodSize=1;

    token=strtok(NULL,",");
    while(token) {
        beasts[i].favoriteFood=realloc(beasts[i].favoriteFood,(beasts[i].favoriteFoodSize+1)*sizeof(char *));
        beasts[i].favoriteFood[beasts[i].favoriteFoodSize]=strdup(token);
        beasts[i].favoriteFoodSize++;

        token=strtok(NULL,",");
    }
}

最后的食物将有一个\n,因为fgets将它保存在它所读取的缓冲液中,所以你可以用它来判断你是否已经完成所有食物的加工(你还需要将它从最后的食物中取出)。或者,如果你没有它,你知道线条更长,你需要阅读更多内容。但根据你的样本数据,这似乎不太可能。

由于您正在进行大量内存分配,因此应确保检查返回的值以确保内存不足。

© www.soinside.com 2019 - 2024. All rights reserved.