实验七

Part 1:验证性实验

  • 验证性实验2

将line 29做出修改后的源代码:

#include <stdio.h> 
#include <stdlib.h>

#define N 10
typedef struct student {
    int num;
    char name[20];
    int score;
}STU;

int main() {
    STU st, stmax, stmin;
    int i;
    FILE *fp;
    
    fp = fopen("file1.dat", "r");
    if( !fp ) {  
        printf("fail to open file1.dat\n");
        exit(0);
    }
    
    stmax.score = 0;    
    stmin.score = 100;
    while( !feof(fp) ) {//修改处,源代码为:for(i=0; i<N; i++)
        fscanf(fp, "%d %s %d", &st.num, st.name, &st.score);  
        if(st.score > stmax.score)
            stmax = st;
        else if(st.score < stmin.score)
            stmin = st; 
    } 
    
    fclose(fp);
    
    printf("最高分学生信息: %5d%15s%5d\n", stmax.num, stmax.name, stmax.score);
    printf("最低分学生信息: %5d%15s%5d\n", stmin.num, stmin.name, stmin.score);

    return 0;
}

 

运行结果:

显然,在不知道总人数的情况下,将line29的代码改为  while( !feof(fp) )  之后,运行结果仍然正确。

这是因为,当fscanf()函数每运行完一行后。函数feof()判断下一行fscanf/fread函数返回值是否出错。若函数返回无错,则feof返回值为0。直到所有内容都被访问,fscanf/fread函数返回错误,feof()返回值为非0,循环结束。

  • 对比验证性实验3和验证性实验4的程序源码及运行结果,总结比较二进制文件与文本文件的区别。

验证性实验3源代码:

#include <stdio.h> 
#include <stdlib.h>

#define N 10


typedef struct student {
    int num;
    char name[20];
    int score;
}STU;

void sort(STU *pst, int n); 

int main() {
    FILE *fin, *fout;
    STU st[N];
    int i;
    fin = fopen("file1.dat", "r");
    if( !fin ) {  
        printf("fail to open file1.dat\n");
        exit(0);
    }
    for(i=0; i<N; i++) 
        fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score);
    fclose(fin); 
    sort(st, N);
    fout = fopen("file3.dat", "w");
    if( !fout ) {  
        printf("fail to open file1.dat\n");
        exit(0);
    }
    for(i=0; i<N; i++) {
        printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score);
        fprintf(fout, "%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score);
    }    
    fclose(fout);  
    return 0;
}

void sort(STU *pst, int n) {
    STU *pi, *pj, t;
    for(pi = pst; pi < pst+n-1; pi++)
        for(pj = pi+1; pj < pst+n; pj++) 
            if(pi->score < pj->score) {
                t = *pi;
                *pi = *pj;
                *pj = t; 
            }
    
} 

运行结果:

验证性实验4代码:

#include <stdio.h> 
#include <stdlib.h>
#define N 10


typedef struct student {
    int num;
    char name[20];
    int score;
}STU;

void sort(STU *pst, int n); 

int main() {
    FILE *fin, *fout;
    STU st[N];
    int i;
    fin = fopen("file1.dat", "r");
    if( !fin ) {  
        printf("fail to open file1.dat\n");
        exit(0);
    }
    for(i=0; i<N; i++) 
        fscanf(fin, "%d %s %d", &st[i].num, st[i].name, &st[i].score);
    fclose(fin); 
    sort(st, N);
    fout = fopen("file3.dat", "wb");
    if( !fout ) {  
        printf("fail to open file1.dat\n");
        exit(0);
    }
    for(i=0; i<N; i++) {
        printf("%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score);
        fprintf(fout, "%-6d%-10s%3d\n", st[i].num, st[i].name, st[i].score);
    }    
    fclose(fout);  
    return 0;
}

void sort(STU *pst, int n) {
    STU *pi, *pj, t;
    for(pi = pst; pi < pst+n-1; pi++)
        for(pj = pi+1; pj < pst+n; pj++) 
            if(pi->score < pj->score) {
                t = *pi;
                *pi = *pj;
                *pj = t; 
            }
    
} 

运行结果:

显然,验证性实验3中,file3是以“w”命令打开的,运行结果以文本文件的方式储存了起来,可以直接阅读;而实验4中,file4以“wb”命令打开,运行结果以二进制文件方式打开,需要专门的解码器才能查看。

p.s.由于在文本文件中,ASCII码每条数据(每个字符)都是1个字节长度固定,而二进制文件的数据是按类型划分,长度并不固定,导致两个数据文件的大小其实是不一样大的:

  • 从二进制文件file4.dat中读出数据,并在屏幕上显示

源代码:

#include<stdio.h>
#include<stdlib.h>

typedef struct student {
    int  num;
    char name[20];
    int  score;
}STU;

int main() { FILE *fp; STU st[10]; int i=0,j; if((fp=fopen("file4.dat","rb"))==NULL){ printf("Failed to open file"); exit(0); } while(!feof(fp)){ if(fread(&st[i],sizeof(struct student),1,fp) == 1) { printf("%d\t%s\t%d\n", st[i].num, st[i].name, st[i].score); i++; } } fclose(fp); return 0; }

运行结果:

注意:feof判断文件结束是通过读取函数fread/fscanf等返回错误来识别的,故而判断文件是否结束应该是在读取函数之后进行判断。比如,在while循环读取一个文件时,如果是在读取函数之前进行判断,则如果文件最后一行是空白行,可能会造成内存错误。这也是为什么有些同学if后面的括号里没有“==1”程序运行会出错的原因。

Part 2:编程练习

源代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const int N = 10;

// 定义结构体类型struct student,并定义其别名为STU 
typedef struct student {
    long int id;
    char name[20];
    float objective;    /*客观题得分*/
    float subjective; /*操作题得分*/
    float sum;
    char level[10];    
}STU; 

// 函数声明
void input(STU s[], int n);
void output(STU s[], int n);
void process(STU s[], int n);

int main() {
    STU stu[N];
    
    printf("录入%d个考生信息: 准考证号,姓名,客观题得分(<=40),操作题得分(<=60)\n", N); 
    input(stu, N);
    
    printf("\n对考生信息进行处理: 计算总分,确定等级\n");
    process(stu, N);
    
    printf("\n打印考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级\n");
    output(stu, N); 
    
    return 0;
} 

// 录入考生信息:准考证号,姓名,客观题得分,操作题得分
void input(STU s[], int n) {
    int i;
    FILE *fin;
    fin=fopen("examinee.txt","r");//只读方式打开"examinee.txt"
    if(fin==NULL){//若打开失败,则显示提示信息,然后退出程序
        printf("fail to open examinee.txt\n");
        exit(0);
    }
    for(i=0;i<n;i++){
    fscanf(fin,"%d %s %f %f",&s[i].id,s[i].name,&s[i].objective,&s[i].subjective);
    }//从原文件读取数据
    fclose(fin);
}

//输出考生完整信息: 准考证号,姓名,客观题得分,操作题得分,总分,等级
void output(STU s[], int n) {
    int i;
    FILE *fout;
    fout=fopen("result.txt","w");// 以只写文本方式打开/创建文件"result.txt"
    for(i=0;i<n;i++){
    printf("%5d %10s %5.1f %5.1f %5.1f %10s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//在屏幕上输出结果
    fprintf(fout,"%5d %10s %5.1f %5.1f %5.1f %10s\n",s[i].id,s[i].name,s[i].objective,s[i].subjective,s[i].sum,s[i].level);//在文件里输出结果
    }
    fclose(fout);
}

void process(STU s[], int n) {
    int i,j,k,m=0;
    STU temp;
    for(i=0;i<n;i++)
        s[i].sum=s[i].objective+s[i].subjective;
    for(j=0;j<n;j++){
        for(k=j;k<n;k++){
            if(s[j].sum<s[k].sum){
                temp=s[j];
                s[j]=s[k];
                s[k]=temp;
            }
        }
    }//对学生总分进行排序
    while(m<=n){
        if(m<=n*0.1-1)
        strcpy(s[m].level,"优秀);
        else if(m>n*0.1-1&&m<=n*0.5-1)
        strcpy(s[m].level,"合格);
        else
        strcpy(s[m].level,"不合格); 
        m++;
    };//评定等级
}

运行结果:

Part 3:拓展综合应用

已知班级学生名单信息存在文本文件list.txt中,编程实现随机抽点任意位学生信息,显示在屏幕上,同时,写入文件
lucky.txt中。

源代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
const int N=80;

typedef struct student {
    int num;
    long int id;
    char name[20];
    char cla[20];
}STU;//定义一个结构体变量

int main(){
    STU rad[N];
    int choose[80];
    int i,j=0,judg=0,key,num;
    FILE *fin,*fout;
    fin=fopen("list.txt","r");// 以只读文本方式打开文件"list.txt"
    if(!fin){
        printf("fail to open the file list.txt\n");
        exit(0);
    }// 如果打开失败,则输出错误提示信息,然后退出程序 
    for(i=0;i<N;i++)
    fscanf(fin,"%d %ld %s %s",&rad[i].num,&rad[i].id,rad[i].name,rad[i].cla);//从文件中录入数据
    printf("please input a number:");
    scanf("%d",&num);//输入想要抽取的人数
    srand(time(NULL));//设置随机数种子
    fout=fopen("lucky.txt","w");// 以只写文本方式打开/创建文件lucky.txt
    fprintf(fout,"the inputed number is:%d\n\n",num);
    do{
        key=rand()%80;//选取一个随机数
        if(j)
            for(i=0;i<j;i++){
                if(key==choose[i])
                    judg=1;
            }
        if(judg==1){
            judg=0;
            continue;
        }//如果选中的随机数已经被选择过,便跳过此次循环
        else{
            printf("%d\t%ld\t%s\t%s\n",rad[key].num,rad[key].id,rad[key].name,rad[key].cla);
            fprintf(fout,"%d\t%ld\t%s\t%s\n",rad[key].num,rad[key].id,rad[key].name,rad[key].cla);//输出结果
            choose[j++]=key;//将选中的随机数保存下来
        }
        judg=0;
    }while(j<num);
    fclose(fin);
    fclose(fout);
    return 0;
}

运行结果:

 评论地址:

https://www.cnblogs.com/tedyoung1/p/11082228.html

https://www.cnblogs.com/hx-123/p/11079428.html

https://www.cnblogs.com/xu9729/p/11070705.html

posted on 2019-06-24 20:58  纪源  阅读(124)  评论(1编辑  收藏  举报

导航