C 无法在结构数组中正确附加元素
这是我在这里的第一篇文章。我正在用C语言编写一个程序来处理小丑游戏的结果(这是一个类似Powerball的游戏)。下面我只包括与我的问题相关的代码。首先,向程序输入1,以便它读取以前的结果文件。我将包含该文件,以便您也可以运行它。然后输入3,以便以C 无法在结构数组中正确附加元素,c,arrays,C,Arrays,这是我在这里的第一篇文章。我正在用C语言编写一个程序来处理小丑游戏的结果(这是一个类似Powerball的游戏)。下面我只包括与我的问题相关的代码。首先,向程序输入1,以便它读取以前的结果文件。我将包含该文件,以便您也可以运行它。然后输入3,以便以 id;day/month/year;num1;num2;num3;num4;num5;joker 然后输入99,就可以看到完整的结果数组。 问题是附加到数组(resArr)的前2个结果显示正确,但以下所有附加结果都以伪随机数存储。你知道为什么我的代
id;day/month/year;num1;num2;num3;num4;num5;joker
然后输入99,就可以看到完整的结果数组。
问题是附加到数组(resArr)
的前2个结果显示正确,但以下所有附加结果都以伪随机数存储。你知道为什么我的代码只能重复两次吗?
文件:
#包括
#包括
typedef结构结果
{
int-id,date[3],num[5],joker;
}结果;
结果*read()
{
文件*fp=fopen(“joker.csv”,“r”);
结果*temp=(结果*)malloc(sizeof(结果));
结果*result=(结果*)malloc(sizeof(结果));
int i=0,size=1;
而(!feof(fp))
{
char*s=(char*)malloc(50*sizeof(char));
fgets(s,50,fp);
sscanf(s),%d;%d/%d/%d;%d;%d;%d;%d;%d;%d;%d“,&result[i].date[0],&result[i].date[1],&result[i].date[2],&result[i].num[0],&result[i].num[1],&result[i].num[2],&result[i].num[3],&result[i].num[4],&result[i].joker);
temp=(结果*)realloc(结果,(++size)*sizeof(结果));
如果(温度)结果=温度;
其他的
{
结果=空;
打破
}
i++;
}
fclose(fp);
返回结果;
}
int findleength()
{
文件*fp=fopen(“joker.csv”,“r”);
int len,i=0;
而(!feof(fp))
{
char*s=(char*)malloc(50*sizeof(char));
fgets(s,50,fp);
i++;
}
fclose(fp);
len=i-1;
回程透镜;
}
void eisagogi(结果*resArr,int*len)
{
结果结果;
printf(“id;dd/mm/yyyy;num1;num2;num3;num4;num5;joker\n”);
scanf(“%d;%d/%d/%d;%d;%d;%d;%d;%d;%d”,&result.id、&result.date[0]、&result.date[1]、&result.date[2]、&result.num[0]、&result.num[1]、&result.num[2]、&result.num[3]、&result.num[4]、&result.joker);
resArr=(结果*)realloc(resArr,(*len+1)*sizeof(结果));
resArr[*len]=结果;
*len=*len+1;
}
无效显示结果(结果*resArr,内部长度)
{
int i;
对于(i=0;i我将您的feof
更改为fgets
char s[50];
while (fgets(s, sizeof(s), fp) != 0) {
现在,您似乎可以添加3个结果并显示它们
#include <stdio.h>
#include <stdlib.h>
typedef struct results {
int id, date[3], num[5], joker;
} Results;
Results *read() {
FILE *fp = fopen("joker.csv", "r");
Results *temp = (Results *) malloc(sizeof(Results));
Results *result = (Results *) malloc(sizeof(Results));
int i = 0, size = 1;
char s[50];
while (fgets(s, sizeof(s), fp) != 0) {
sscanf(s, "%d;%d/%d/%d;%d;%d;%d;%d;%d;%d", &result[i].id, &result[i].date[0], &result[i].date[1],
&result[i].date[2], &result[i].num[0], &result[i].num[1], &result[i].num[2], &result[i].num[3],
&result[i].num[4], &result[i].joker);
temp = (Results *) realloc(result, (++size) * sizeof(Results));
if (temp) result = temp;
else {
result = NULL;
break;
}
i++;
}
fclose(fp);
return result;
}
int findLength() {
FILE *fp = fopen("joker.csv", "r");
int len, i = 0;
while (!feof(fp)) {
char *s = (char *) malloc(50 * sizeof(char));
fgets(s, 50, fp);
i++;
}
fclose(fp);
len = i - 1;
return len;
}
void eisagogi(Results *resArr, int *len) {
Results result;
printf("id;dd/mm/yyyy;num1;num2;num3;num4;num5;joker\n");
scanf("%d;%d/%d/%d;%d;%d;%d;%d;%d;%d", &result.id, &result.date[0], &result.date[1], &result.date[2],
&result.num[0], &result.num[1], &result.num[2], &result.num[3], &result.num[4], &result.joker);
resArr = (Results *) realloc(resArr, (*len + 1) * sizeof(Results));
resArr[*len] = result;
*len = *len + 1;
}
void showResults(Results *resArr, int len) {
int i;
for (i = 0; i < len; i++) {
printf("%d;%d/%d/%d;%d;%d;%d;%d;%d;%d\n", resArr[i].id, resArr[i].date[0], resArr[i].date[1], resArr[i].date[2],
resArr[i].num[0], resArr[i].num[1], resArr[i].num[2], resArr[i].num[3], resArr[i].num[4],
resArr[i].joker);
}
}
int menuChoose() {
int choice;
printf("Load results 1\n");
printf("Append result 3\n");
printf("Result array 99\n");
printf("Exit 0\n");
scanf("%d", &choice);
return choice;
}
int main() {
Results *resArr = (Results *) malloc(sizeof(Results));
int choice, len;
while (1) {
choice = menuChoose();
switch (choice) {
case 1:
resArr = read();
len = findLength();
break;
case 3:
eisagogi(resArr, &len);
break;
case 99:
showResults(resArr, len);
break;
case 0:
exit(0);
break;
}
}
return 0;
}
您的I/O策略有一部分是脆弱的,另一部分是完全错误的
首先,。正如链接问题的答案所详细解释的,feof()
函数报告指定流上是否已检测到文件结尾。它无法报告下次尝试读取时是否会遇到EOF,因此您需要在每次读取时注意EOF。在这种情况下,您需要验证fgets()
是否没有返回NULL,正如@DacSaunders已经建议的那样:
char s[50];
while (fgets(s, sizeof(s), fp) != NULL) {
(整数文本0
也用作空指针常量,但我发现使用null
更清晰)还请注意,Dac将您的s
更改为自动数组,而不是动态分配。这不仅更易于管理,而且还清除了原始代码因每行动态分配50个字节而出现的内存泄漏,并且从未释放它们。这还允许您使用sizeof(s)
以获得s
的容量——这适用于数组,但不适用于指针
第二,您不检查输入
>P>您应该验证每个代码> FGETSH()/COD>实际上读取一个完整的行(可以通过在数据读取中寻找换行符来确定),因为下一个读取将在最后一个被关闭的地方拾取,并且可以在一条直线的中间。
- 您应该验证每个
sscanf()
实际上是否匹配每个预期字段(通过检查其返回值),因为如果它不匹配,则尝试填充的部分或甚至所有字段都将未初始化。如果输入格式不正确,或者输入行太长,则可能会出现这种故障
额外提示:您还有另一个内存泄漏,即您在声明中为temp
分配内存,但您从未释放它,甚至也没有使用它。声明指针并不意味着您必须分配内存。非常感谢!我也重复了Dac在findleLength中的更改,并且在read()中使用temp()释放temp()。
这个错误是因为内存泄漏而发生的吗?你能展示一个程序运行的例子并解释输出与你想要的不同吗?p.s.确保free()
任何你malloc()
或realloc()的指针
。修复你的问题。答案是为了答案,而不是说谢谢。你可以在对答案的评论中说谢谢。
Load results 1
Append result 3
Result array 99
Exit 0
3
id;dd/mm/yyyy;num1;num2;num3;num4;num5;joker
1768;18/12/2016;11;28;5;9;31;1
Load results 1
Append result 3
Result array 99
Exit 0
3
id;dd/mm/yyyy;num1;num2;num3;num4;num5;joker
1769;18/12/2016;11;28;5;9;31;2
Load results 1
Append result 3
Result array 99
Exit 0
3
id;dd/mm/yyyy;num1;num2;num3;num4;num5;joker
1770;18/12/2016;11;28;5;9;31;3
Load results 1
Append result 3
Result array 99
Exit 0
1
...
1768;18/12/2016;11;28;5;9;31;1
1769;18/12/2016;11;28;5;9;31;2
1770;18/12/2016;11;28;5;9;31;3
Load results 1
Append result 3
Result array 99
Exit 0
char s[50];
while (fgets(s, sizeof(s), fp) != NULL) {