Ⅰ 利用C語言讀取含文件頭的txt文本並將學生信息和成績分別保存到數組
思路:
1、fgets每次讀取一行,根據文本格式找到姓名和分數的行字元串。
2、分別解析行字元串,獲取其中的姓名和成績(成績字元串拆解後用atof函數轉換成浮點數保存在浮點數數組中)。
3、通過malloc和realloc申請一個對應大小的結構數組(你題目要求用數組,換成鏈表更好)
4、將解析的數據保存到結構數組成員中。
注意:代碼是根據你提供的樣本格式解析的,如格式發生改變,需自行修改條件
注意:你成績之後內容沒有貼出來,所以成績內容到哪裡為結束,我只能參照姓名的個數。如成績行數比姓名行數多,多餘的會被忽略。
下面是我寫得演示代碼,已詳細備注(注意我的函數你如想單獨調用,注意free釋放內存):
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#define M 1000 //預估一行最大字元數,必須大於等於文本一行最大長度
#define S 5 //預讀取的成績科目數量
int slen=0;//學生人數
typedef struct student
{
char *name;//姓名
float *scores;//成績數組
}STU;
/*getaLine每調用一次讀取一行字元串(返回的是動態申請地址,如你要單獨調用該函數,記得free釋放)
函數用靜態變數記錄文件指針偏移量。參數傳非0每次調用往下行讀取,參數傳0從第一行重新讀取
讀取成功返回字元串首地址,失敗或者讀取到文件末尾返回NULL
*/
char *getaLine();
/*
getName截取名字,注意該函數只是截取,多餘字元空間沒有刪除,如單獨調用該函數自行處理地址空間。
參數傳入包含名字的那一行字元串,根據內容規則遇到第一個數字就在前一個字元置0
成功返回處理後的字元串首地址,失敗返回NULL
*/
char *getName(char *nameStr);
float *getScores(char *scoreStr);//通過字元串空格分隔格式截取各科成績,重組浮點數數組返回。異常返回NULL
STU *getNamesAndScore();
int main()
{
int i,j;
STU *stus=NULL;
stus=getNamesAndScore();
if(!stus) return 1;
for(i=0;i<slen;i++)
{
printf("姓名:%s ",stus[i].name);
for(j=0,printf("成績:");j<S;j++)
printf("%.2f ",stus[i].scores[j]);
printf(" ");
}
return 0;
}
STU *getNamesAndScore()
{
int flag=0,n=1,scnt=0;
STU *stups=NULL,*spTemp=NULL;
char *sLine=NULL;
while(1)
{
sLine=getaLine(1);
if(!sLine) break;//文件讀取到末尾或異常
if(sLine[0]=='#' && sLine[1]=='-' && sLine[2]=='-' && sLine[3]=='-'&& sLine[4]=='-'&& sLine[5]=='-')
{
flag++;
continue;
}
if(flag==2 && sLine[0]=='~' && sLine[1]=='A' && sLine[2]==' ' && sLine[3]=='C' && sLine[4]=='h'&& sLine[5]=='i')
{
continue;
}
if(flag==0) continue;
if(flag==1)//開始讀取姓名
{
if(!stups)
{
stups=(STU *)malloc(sizeof(STU));
if(!stups) return NULL;
}
else
{
n++;
spTemp=(STU *)realloc(stups,sizeof(STU)*n);
if(!spTemp) return NULL;
stups=spTemp;
}
slen++;
getName(sLine);
stups[n-1].name=(char *)malloc(sizeof(char)*(strlen(sLine)+1));
strcpy(stups[n-1].name,sLine);
free(sLine);
}
if(flag==2)//開始讀取成績
{
scnt++;
stups[scnt-1].scores=getScores(sLine);
if(!stups[scnt-1].scores)return NULL;
if(scnt==slen) break;//確保成績和姓名個數匹配,只讀對應行數的成績
}
}
return stups;
}
float *getScores(char *scoreStr)
{
int n=0;
char *p0=scoreStr,*p1=scoreStr;
float *scs=NULL;
scs=(float *)malloc(sizeof(float)*S);
if(!scs)return NULL;
while(*p1!=0)
{
if(*p1==' ')
{
*p1=0;
scs[n++]=atof(p0);
p0=p1+1;
}
p1++;
}
scs[n]=atof(p0);
return scs;
}
char *getName(char *nameStr)
{
char *p=nameStr;
if(!nameStr)return NULL;
while(*p!=0)
{
if(*p>='0' && *p<='9')
{
*(p-1)=0;
break;
}
p++;
}
return nameStr;
}
char *getaLine(int origin)
{
static long offsetSave=0;
int len=0;
char strTemp[M]={0},*rp=NULL,*sLine=NULL;
FILE *fp=NULL;
if(!origin) offsetSave=0;
fp=fopen("C:\testData.txt","r");
if(!fp) return NULL;
fseek(fp,offsetSave,SEEK_SET);
rp=fgets(strTemp,M,fp);
if(!rp)return NULL;
len=strlen(rp);
offsetSave+=len+1;
fclose(fp);
sLine=(char *)malloc(sizeof(char)*(len+1));
if(!sLine) return NULL;
strcpy(sLine,rp);
return sLine;
}