文本文件保存关于垒球队的信息。每一行的数据排列如下:
杰茜·乔伊巴特4 5 2 1 1
第一项是玩家的号码,方便地在0-18范围内。第二项是玩家的名字,第三项是玩家的姓。每个名字都是一个单词。下一个项目是球员在蝙蝠的官方时间,然后是击球次数、步行次数和击球次数(RBI)。该文件可能包含多个游戏的数据,因此同一玩家可能有多行数据,并且在这些行之间可能有其他玩家的数据。编写一个将数据存储到结构数组中的程序。这个结构应该有成员来表示名字和姓氏,例如蝙蝠、击球、步行和打点(跑步),以及击球平均数(待会儿计算)。您可以使用播放机编号作为数组索引。程序应该读取到文件的末尾,并且应该保持每个玩家的累计总数.
棒球统计是一个牵涉其中的世界。例如,一次步行或基于错误到达的基础并不算作是一个bat,而是可能产生一个RBI。但是这个程序所要做的就是读取和处理数据文件,就像下面描述的那样,而不必担心数据有多真实。
程序进行的最简单的方法是将结构内容初始化为零,将文件数据读入临时变量,然后将它们添加到相应结构的内容中。程序读取完文件后,应该计算每个玩家的击球平均值,并将其存储在相应的结构成员中。击球平均数是通过将一名球员的累计击球次数除以球拍的累积次数来计算的;它应该是一个浮点数计算。然后,该程序应该显示每个玩家的累积数据,以及显示整个团队的合并统计数据的一行。
team.txt (我正在处理的文本文件):
4 Jessie Joybat 5 2 1 1
4 Jessie Joybat 7 3 5 3
7 Jack Donner 6 3 1 2
11 Martin Garder 4 3 2 1
15 Jaime Curtis 7 4 1 2
2 Curtis Michel 3 2 2 3
9 Gillan Morthim 9 6 6 7
12 Brett Tyler 8 7 4 3
8 Hans Gunner 7 7 2 3
14 Jessie James 11 2 3 4
12 Brett Tyler 4 3 1 3因为我是C语言的初学者,所以要么我误解了最初要求的任务,要么它不太复杂(我相信前者就是如此)。我太迷茫了,我想不出怎样才能用指数(玩家数量)的标准来填写每一张数据,跟踪他是否有不止一场比赛,计算和获取球棒平均数,然后打印。
到目前为止,我得到的是:
#define LGT 30
struct profile {
int pl_num;
char name[LGT];
char lname[LGT];
int atbat[LGT/3];
int hits[LGT/3];
int walks[LGT/3];
int runs[LGT/3];
float batavg;
};
//It's wrong obviously but it's a starting point
int main(void)
{
FILE *flx;
int i,jc,flow=0;
struct profile stat[LGT]={{0}};
if((flx=fopen("team.txt","r"))==NULL) {
fprintf(stderr,"Can't read file team!\n");
exit(1);
}
for( jc = 0; jc < 11; jc++) {
fscanf(flx,"%d",&i);
stat[i].pl_num=i;
fscanf(flx,"%s",&stat[i].name);
fscanf(flx,"%s",&stat[i].lname);
fscanf(flx,"%d",&stat[i].atbat[flow]);
fscanf(flx,"%d",&stat[i].hits[flow]);
fscanf(flx,"%d",&stat[i].walks[flow]);
fscanf(flx,"%d",&stat[i].runs[flow]);
flow++;
}
}发布于 2012-03-08 14:37:39
建议1:不要声明像atbat[LGT/3]这样的数组。
建议2:与多个fscanf不同,您可以一次读整行。
建议3:由于玩家的数量是有限的,并且玩家的数量有一个很好的范围(0-18),所以使用这个玩家号作为结构数组的索引是个好主意。
建议4:因为您需要每个玩家的累积数据(不需要存储他的历史点数),所以您不需要整数数组,只需要一个整数来表示总数。
所以:
#include <stdio.h>
#define PLAYERS_NO 19
typedef struct
{
char name[20+1];
char lastName[25+1];
int atbat;
int hits;
int walks;
int runs;
float batavg;
} Profile;
int main(int argc, char** argv)
{
Profile stats[PLAYERS_NO];
int i;
FILE* dataFile;
int playerNo;
Profile tmpProfile;
int games = 0;
for(i=0; i<PLAYERS_NO; ++i)
{
stats[i].name[0] = '\0';
stats[i].lastName[0] = '\0';
stats[i].atbat = 0;
stats[i].hits = 0;
stats[i].walks = 0;
stats[i].runs = 0;
}
dataFile = fopen("team.txt", "r");
if ( dataFile == NULL )
{
fprintf(stderr, "Can't read file team!\n");
exit(1);
}
for(i=0; i<PLAYERS_NO && !feof(dataFile); ++i, ++games)
{
fscanf(dataFile, "%d", &playerNo);
if ( playerNo <0 || playerNo > PLAYERS_NO )
{
fprintf(stderr, "Player number out of range\n");
continue;
}
fscanf(dataFile, "%s %s %d %d %d %d",
&tmpProfile.name,
&tmpProfile.lastName,
&tmpProfile.atbat,
&tmpProfile.hits,
&tmpProfile.walks,
&tmpProfile.runs);
printf("READ: %d %s %s %d %d %d %d\n",
playerNo,
tmpProfile.name,
tmpProfile.lastName,
tmpProfile.atbat,
tmpProfile.hits,
tmpProfile.walks,
tmpProfile.runs);
strcpy(stats[playerNo].name, tmpProfile.name);
strcpy(stats[playerNo].lastName, tmpProfile.lastName);
stats[playerNo].atbat += tmpProfile.atbat;
stats[playerNo].hits += tmpProfile.hits;
stats[playerNo].walks += tmpProfile.walks;
stats[playerNo].runs += tmpProfile.runs;
}
/* exercise: compute the average */
fclose(dataFile);
for(i=0; i<PLAYERS_NO; ++i)
{
if ( stats[i].name[0] == '\0' )
continue;
printf("%d %s %s %d %d %d %d\n",
i,
stats[i].name,
stats[i].lastName,
stats[i].atbat,
stats[i].hits,
stats[i].walks,
stats[i].runs);
}
return 0;
}发布于 2012-03-08 14:24:42
编程的第一条规则是:分而治之。
所以你需要识别个别的行动。其中一个操作是“加载一行输入”,另一个是“查找播放机”。如果您有一些这样的操作(随着时间的推移还会有更多的操作),您可以开始构建您的程序:
while( more_input ) {
row = load_one_row()
player = find_player( row.name )
if( !player ) {
player = create_player( row.name )
add_player( player )
}
... do something with row and player ...
}当你有了它,你可以开始写所有的函数。
这里重要的一点是编写测试用例。从一个简单的输入开始,测试代码来读取一行。你得到正确的结果了吗?
如果是这样的话,测试代码以查找/创建播放器。
测试用例确保您可以忘记已经工作的代码。
为此使用像检查这样的框架。
发布于 2012-03-08 14:32:04
如果我是这样做的,我将从一个只包含一组“数据”的结构开始,然后创建一个这些结构的数组:
struct profile {
char name[NAMELEN];
char lname[NAMELEN];
int atbat;
int hits;
int walks;
int runs;
float batavg;
};因为您使用播放机的数字作为数组中的索引,所以不需要将其存储到结构中。
我认为这会使问题简化一点。您不需要为单个播放器存储多个数据项--当您得到一个副本时,您只需忽略一些新的数据(比如名称,应该是相同的),然后对其他数据(例如,击棒、命中)进行汇总。
https://stackoverflow.com/questions/9618811
复制相似问题