c - 动态 fscanf 成数组
问题描述
我正在尝试将一些文本放入我的数组的结构部分中,这是一个包含部分文本的数组。
例如我的结构是:
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++
}
我该怎么做呢?
解决方案
首先,您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 个字符……或者将其设为 a 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
保存它读取的缓冲区,因此您可以使用它来判断您是否已经完成了所有食物的处理(您还需要从最后一个食物中删除它)。或者如果你没有它,你知道这条线更长,你需要阅读更多内容。但根据你的样本数据,这似乎不太可能。
而且由于您正在分配大量内存,因此您应该确保检查返回的值以确保您没有耗尽内存。
推荐阅读
- javascript - Android 依赖项有不同的版本 - 分辨率不起作用
- java - java.net.SocketException:连接重置,在 GET 页面上使用 HttpURLConnection
- google-apps-script - 如何通过自动 Gmail Google 脚本将非 Google Drive 文件附加到电子邮件
- python - 检查熊猫数据框中的几列是否重合并将它们标记在新列中
- mysql - 如果第一个为空,则使用 MySQL 选择第二列值?
- unity3d - Unity:让相机滚动而不是跳转到某个位置
- java - 用另一个数组中的值填充一个多维数组
- laravel - 自定义路线推翻新星路线
- css - 将带有字体 url 的 SCSS 文件导入到具有不同文件夹级别的不同 scss 文件中
- c# - 通过 Id 列表搜索数据库中的记录