利用C语言读取含文件头的txt文本并将学生信息和成绩分别保存到数组?

上边文本信息是一个文件名为“~成绩单.txt”的内容,包含了学生的姓名学号和五门课的成绩,原文件太大,只列出两个学生。怎样利用C语言读取该txt文档,并将学生姓名学号保存在一个数组,将五门课的成绩保存在一个数组里面,该怎么编程呢,谢谢。
~ data list
~Time 2014/07/14
~data information
#Name Student ID Information
#---------- ------------------------ ----------------
Li Mingxue 2013080237 academic record
Han Lei 2013080238 academic record
#--------------------------------------------------------
~A Chinese Math English Nature Politics
89.50 92.50 85.25 94.75 78.35
86.75 90.25 89.00 89.75 85.50

第1个回答  2021-08-28

思路:

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\n",stus[i].name);

        for(j=0,printf("成绩:");j<S;j++)

            printf("%.2f ",stus[i].scores[j]);

        printf("\n");

    }

    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;

}