Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103639626
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: C/C++

2008-04-17 16:44:37

 

7.1 结构体类型变量的定义和引用
    7.1.1 结构体类型变量的定义
    7.1.2 结构体类型变量的引用
    7.1.3 结构体类型变量的初始化
7.2 结构体数组的定义和引用


    前面的课程我们学习了一些简单数据类型(整型、实型、字符型)的定义和应用,还学习了数组(一维、二维)的定义和应用,这些数据类型的特点是:当定义某一特定数据类型,就限定该类型变量的存储特性和取值范围。对简单数据类型来说,既可以定义单个的变量,也可以定义数组。而数组的全部元素都具有相同的数据类型,或者说是相同数据类型的一个集合。
    在日常生活中,我们常会遇到一些需要填写的登记表,如住宿表、成绩表、通讯地址等。在这些表中,填写的数据是不能用同一种数据类型描述的,在住宿表中我们通常会登记上姓名、性别、身份证号码等项目;在通讯地址表中我们会写下姓名、邮编、邮箱地址、电话号码、E - mail等项目。这些表中集合了各种数据,无法用前面学过的任一种数据类型完全描述,
    因此C引入一种能集中不同数据类型于一体的数据类型—结构体类型。结构体类型的变量可以拥有不同数据类型的成员,是不同数据类型成员的集合。

7.1 结构体类型变量的定义和引用
在上面描述的各种登记表中,让我们仔细观察一下住宿表、成绩表、通讯地址等。
住宿表由下面的项目构成:


这些登记表用C提供的结构体类型描述如下:
住宿表:
struct accommod
{
    char name[20]; /*姓名*/
    char sex; /*性别*/
    char job[40]; /*职业*/
    int age; /*年龄*/
    long number; /*身份证号码*/
} ;
成绩表:
struct score
{
    char grade[20]; /* 班级*/
    long number; /* 学号*/
    char name[20]; /*姓名*/
    float os; /*操作系统*/
    float datastru; /* 数据结构*/
    float compnet; /* 计算机网络*/
} ;
通讯地址表:
struct addr
{
    char name[20];
    char department[30];/* 部门*/
    char address[30]; /*住址*/
    long box; /* 邮编*/
    long phone; /* 电话号码*/
    char email[30]; /* Email */
};
    这一系列对不同登记表的数据结构的描述类型称为结构体类型。由于不同的问题有不同的数据成员,也就是说有不同描述的结构体类型。我们也可以理解为结构体类型根据所针对的问题其成员是不同的,可以有任意多的结构体类型描述。
下面给出C对结构体类型的定义形式:
struct 结构体名
{
    成员项表列;
};
    有了结构体类型,我们就可以定义结构体类型变量,以对不同变量的各成员进行引用。

7.1.1 结构体类型变量的定义
    结构体类型变量的定义与其它类型的变量的定义是一样的,但由于结构体类型需要针对问题事先自行定义,所以结构体类型变量的定义形式就增加了灵活性,共计有三种形式,分别介绍如下:
1) 先定义结构体类型,再定义结构体类型变量:
struct stu / *定义学生结构体类型* /
{
    char name[20]; /* 学生姓名*/
    char sex; /* 性别*/
    long num; /*学号*/
    float score[3]; /* 三科考试成绩*/
};
struct stu student1,student2;/* 定义结构体类型变量*/
struct stu student3,student4;
     用此结构体类型,可以定义更多的该结构体类型变量。
2 ) 定义结构体类型同时定义结构体类型变量:
struct data
{
    int day;
    int month;
    int year;
} time1,time2;
    也可以再定义如下变量:
struct data time3,time4;
    用此结构体类型,同样可以定义更多的该结构体类型变量。

3) 直接定义结构体类型变量:
struct
{
    char name[20]; /*学生姓名*/
    char sex; /*性别*/
    long num; /*学号*/
    float score[3]; /*三科考试成绩*/
} person1,person2; /*定义该结构体类型变量* /
    法由于无法记录该结构体类型,所以除直接定义外,不能再定义该结构体类型变量。

7.1.2 结构体类型变量的引用
    学习了怎样定义结构体类型和结构体类型变量,怎样正确地引用该结构体类型变量的成员呢?C 规定引用的形式为:
    类型变量名> . <成员名>
    若我们定义的结构体类型及变量如下:
struct data
{
    int day;
    int month;
    int year;
} time1,time2;
   则变量time1和time2各成员的引用形式为:time1.day、time1.month、time1.year及time2.day、time2.month、time2.yea r,如图7 - 1所示。


    类型变量的各成员与相应的简单类型变量使用方法完全相同。

7.1.3 结构体类型变量的初始化
    由于结构体类型变量汇集了各类不同数据类型的成员,所以结构体类型变量的初始化就略显复杂。
结构体类型变量的定义和初始化为:
struct stu / *定义学生结构体类型* /
{
    char name[20]; / * 学生姓名* /
    char sex; / * 性别* /
     long num; / *学号* /
     float score[3]; / * 三科考试成绩* /
};
struct stu student={"liping",'f',970541,98.5,97.4,95};
    上述对结构体类型变量的三种定义形式均可在定义时初始化。结构体类型变量完成初始化后,即各成员的值分别为: student.name = "liping"、student.sex = 'f'、student.num = 970541、student.sco re[0] = 98.5、student.score[1] = 97.4、student.score[2] = 95。其存储在内存的情况如图7 - 2所示。

    我们也可以通过C提供的输入输出函数完成对结构体类型变量成员的输入输出。由于结构体类型变量成员的数据类型通常是不一样的,所以要将结构体类型变量成员以字符串的形式输入,利用C的类型转换函数将其转换为所需类型。类型转换的函数是:
    int atoi( char *str);转换str所指向的字符串为整型,其函数的返回值为整型。
    double atof(char *str);转换str所指向的字符串为实型,其函数的返回值为双精度的实型。
    long atol(char *str);转换str所指向的字符串为长整型,其函数的返回值为长整型。
    使用上述函数,要包含头文件"stdlib.h"。
    对上述的结构体类型变量成员输入采用的一般形式:
char temp[20];
gets(student.name); /* 输入姓名*/
student.sex = getchar( ); /* 输入性别*/
gets(temp); /*输入学号*/
student.num = atol(temp); /* 转换为长整型*/
for( i = 0; i < 3; i ++) /*输入三科成绩*/
{
    gets(temp);
    student.score[i] = atoi(temp);
}
    对该结构体类型变量成员的输出也必须采用各成员独立输出,而不能将结构体类型变量以整体的形式输入输出。
C允许针对具体问题定义各种各样的结构体类型,甚至是嵌套的结构体类型。
struct data
{
    int day;
    int mouth;
    int year;
};
struct stu
{
    char name[20];
    struct data birthday; /* 出生年月,嵌套的结构体类型*/
    long num;
} person;

    该结构体类型变量成员的引用形式: person.name 、person.birthday.day、person. birthday.month、person. birthday.year、person.num 。

7.2 结构体数组的定义和引用
    单个的结构体类型变量在解决实际问题时作用不大,一般是以结构体类型数组的形式出现。结构体类型数组的定义形式为:
struct stu /*定义学生结构体类型*/
{
    char name[20]; /*学生姓名*/
    char sex; /*性别*/
    long num; /*学号*/
    float score[3]; /*三科考试成绩*/
};
struct stu stud[20]; /* 定义结构体类型数组stud ,*/
/ *该数组有2 0个结构体类型元素* /
其数组元素各成员的引用形式为:
stud[0].name 、stud[0].sex、stud[0].score[i];
stud[1].name、stud[1].sex、stud[1].score[i];
. . .
. . .
stud[19].name、stud[19].sex、stud[19].score[i];

[例7-1] 设某组有4 个人,填写如下的登记表,除姓名、学号外,还有三科成绩,编程实现对表格的计算,求解出每个人的三科平均成绩,求出四个学生的单科平均,并按平均成绩由高分到低分输出。
Number Name English Mathemr Physics Average
1 Liping 78 98 76 .
2 Wanglin 66 90 86 .
3 Jiangbo 89 70 76 .
4 Yangming 90 100 67 .


题目要求的问题多,采用模块化编程方式,将问题进行分解如下:
1) 结构体类型数组的输入。
2) 求解各学生的三科平均成绩。
3) 按学生的平均成绩排序。
4) 按表格要求输出。
5) 求解组内学生单科平均成绩并输出。
6) 定义m a i n ( )函数,调用各子程序。
第一步,根据具体情况定义结构体类型。
struct stu
{
    char name[20]; /*姓名* /
    long number; /*学号* /
    float score[4]; /* 数组依此存放English、Mathema、Physics,及Average*/
} ;
    由于该结构体类型会提供给每个子程序使用,是共用的,所以将其定义为外部的结构体类型,放在程序的最前面。
第二步,定义结构体类型数组的输入模块。
void input(arr,n) /*输入结构体类型数组arr 的n个元素*/
struct stu arr[];
int n;
{
     int i,j;
    char temp[30];
    for (i=0;i    {
        printf("\ninput name,number,English,mathema,physic\n"); /*打印提示信息* /
        gets(arr[i].name); /* 输入姓名*/
        gets(temp); /* 输入学号*/
        arr[i].number = atol(temp);
        for(j = 0; j < 3; j++)
        {
            gets(temp); /*输入三科成绩* /
            arr[i].score[j] = atoi(temp);
        }
    }
}
第三步,求解各学生的三科平均成绩。
在结构体类型数组中第i个元素arr[i]的成员score的前三个元素为已知,第四个Average需计算得到。
void aver(arr,n)
struct stu arr[];
int n;
{
    int i,j;
    for(i=0;i    {
        arr[i].score[3] = 0;
        for(j=0;j<3;j++)
            arr[i].score[3]=arr[i].score[3]+arr[i].score[j]; /* 求和*/
        arr[i].score[3]=arr[i].score[3] /3; /* 平均成绩* /
    }
}
第四步,按平均成绩排序,排序算法采用冒泡法。
void order(arr,n)
struct stu arr[];
int n;

    struct stu temp;
    int i,j,x,y;
    for(i = 0; i < n - 1; i++)
        for( j = 0; j < n - 1 - i; j++)
            if (arr[j].score[3]>arr[j+1].score[3])
            { 
                temp=arr[j]; /* 结构体类型变量不允许以整体输入或输出,但允许相互赋值* /
                arr[j]=arr[j+1]; /*进行交换* /
                arr[j + 1] = temp;
            }
}
第五步,按表格要求输出。
void output(arr,n) /*以表格形式输出有n个元素的结构体类型数组各成员*/
int n;struct stu arr[];
{
    int i,j;
    printf("********************TABLE********************\n"); /* 打印表头*/
    printf("----------------------------------------------------\n");
    /*输出一条水平线*/
    printf("|%10s|%8s|%7s|%7s|%7s|%7s|\n","Name","Number", "English", "Mathema","physics","average");
    /*输出效果为:| Name| Number|English|Mathema|Physics|Average|*/
    printf("----------------------------------------------------\n");
    for (i=0;i    {
        printf("|%10s|%8ld|",arr[i].name,arr[i].number); /* 输出姓名、学号*/
        for(j=0;j<4;j++)
        printf("%7.2f|",arr[i].score[j]);/*输出三科成绩及三科的平均*/
        printf("\n");
        printf("---------------------------------------------------\n");
    }
}
第六步,求解组内学生单科平均成绩并输出。在输出表格的最后一行,输出单科平均成绩及总平均。
void out_row(arr,n) /*对n个元素的结构体类型数组求单项平均*/
int n;
struct stu arr[];
{
    float row[4]={0,0,0,0};/*定义存放单项平均的一维数组*/
    int i,j;
    for( i = 0; i < 4; i++)
    {
        for(j=0; j        row[i] = row[i] + arr[j].score[i]; /* 计算单项总和*/
        row[i]=row[i]/n; /* 计算单项平均*/
    }
    printf("|%19c|",' '); /* 按表格形式输出*/
    for (i=0;i<4;i++)
    printf("%7.2f|",row[i]);
    printf("\n------------------------------------------\n");
}
第七步,定义main( )函数,列出完整的程序清单。
#include
#include
struct stu
{
    char name[20];
    long number;
    float score[4];
} ;
main( )
{
    void input(); /*函数声明*/
    void aver();
    void order();
    void output();
    void out_row();
    struct stu stud[4]; /* 定义结构体数组*/
    float row[3];
    input(stud, 4); /*依此调用自定义函数*/
    aver(stud,4);
    order(stud,4);
    output(stud, 4);
    out_row(stud,4);
}
/****************************/
void input(arr,n)
struct stu arr[];
int n;
{
    int i,j;
    char temp[30];
    for (i=0;i    {
        printf("\nInput Name,Number,English,Mathema,Physic\n");
        gets(arr[i].name);
        gets(temp);
        arr[i].number=atol(temp);
        for(j=0;j<3;j++)
        {
            gets(temp);
            arr[i].score[j]=atoi(temp);
        }
    }
}
/ *****************************************/
void aver(arr,n)
struct stu arr[];
int n;
{
    int i,j;
    for(i=0;i    {
        arr[i].score[3]=0;
        for(j=0;j<3;j++)
            arr[i].score[3]=arr[i].score[3]+arr[i].score[j];
        arr[i].score[3]=arr[i].score[3]/3;
    }
}
/*********************************************/
void order(arr,n)
struct stu arr[];
int n;
{
    struct stu temp;
    int i,j,x,y;
    for(i=0;i        for(j=0;j            if (arr[j].score[3]>arr[j+1].score[3])
            {
                temp=arr[j];
                arr[j] = arr[j+1];
                arr[j+1]=temp;
            }
}
/**********************************************/
void output(arr,n)
int n;
struct stu arr[];
{
    int i,j;
    printf("********************TABLE********************\n");
    printf("-------------------------------------------------\n");
    printf("|%10s|%8s|%7s|%7s|%7s|%7s|\n","Name","Number","English","mathema","physics","average");
    printf("-------------------------------------------------\n");
    for (i=0;i    {
        printf("|%10s|%8ld|",arr[i].name,arr[i].number);
        for(j=0;j<4;j++)
        printf("%7.2f|",arr[i].score[j]);
        printf("\n");
        printf("----------------------------------------------\n");
    }
}
/*********************************************/
void out_row(arr,n)
int n;
struct stu arr[];
{
    float row[4]={0,0,0,0};
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j        row[i]=row[i]+arr[j].score[i];
        row[i]=row[i]/n;
    }
    printf("|%19c|",' ');
    for (i=0;i<4;i++)
    printf("%7.2f|",row[i]);
    printf("\n-------------------------------------------------------\n");
}
运行程序:
Input Name,Number,English,Mathema,Physic
Liping
1
78
98
76
Input Name,Number,English,Mathema,Physic
Wangling
2
66
90
86
Input Name,Number,English,Mathema,Physic
Jiangbo
3
89
70
76
Input Name,Number,English,Mathema,Physic
Yangming
4
90
100

********************* T A B L E ************************
---------------------------------------------
|   Number|   Name|English| Mathema| Physics| Average|
---------------------------------------------
| Yangming|      4| 90.00|   100.00|   67.00|  85.67|
---------------------------------------------
|  Liping |      1| 78.00|   98.00|  76.00|  84.00|
---------------------------------------------
| Wangling|      2| 66.00|   90.00|   86.00|  80.72|
---------------------------------------------
| Jiangbo |      3| 89.00|  70.00|   76.00|   78.33|
---------------------------------------------
|         |         80.75|   89.50|   76.25|  82.18|
---------------------------------------------
    程序中要谨慎处理以数组名作函数的参数。由于数组名作为数组的首地址,在形参和实参结合时,传递给子程序的就是数组的首地址。形参数组的大小最好不定义,以表示与调用函数的数组保持一致。在定义的结构体内,成员score [3]用于表示计算的平均成绩,也是我们用于排序的依据。我们无法用数组元素进行相互比较,而只能用数组元素的成员score[3]进行比较。在需要交换的时候,用数组元素的整体包括姓名、学号、三科成绩及平均成绩进行交
换。在程序order()函数中,比较采用: arr[j].score[3]>arr[j+1].score[3],而交换则采用:
arr[j] <------> arr[j+1]

阅读(186) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~