多做题!
多做题!
理论讲解
一、用typedef定义类型
(一)用typedef定义类型的方法(了解)
C语言不仅提供了丰富的数据类型,而且还允许用关键字typedef定义一种新的类型名来代替已有的类型名。
typedef定义新类型名的一般形式为:
typedef 原类型名 新类型名
其中原类型中含有定义的部分,新类型名一般用大写表示,以便于区别。
例如:
typedef int INTEGER; typedef float REAL;
定义了新的数据类型,INTEGER和REAL,它们分别代表已有数据类型int和float。
则:
> INTEGER a,b; 等效于:int a,b; REAL x,y; 等效于:float x,y;
二、结构体类型的定义
(一)定义一个结构体类型的一般形式
“结构体”是一种构造类型,它由若干“成员”组成。每一个成员可以是一个基本数据类型或者又是一个构造类型。结构体既然是一种“构造”而成的数据类型,那么在使用之前必须先定义它,也就是构造它。
定义一个结构体类型的一般形式为:
struct [结构体名] { 类型标识符1 成员名1; 类型标识符2 成员名2; ... ... 类型标识符n 成员名n; };
说明
- struct是关键字,在定义和使用中都不能省略,
- 结构体中的每个成员均须作类型说明,结构体类型名和成员名的命名应符合标识符的命名规则。
- 成员名可以与程序中的变量名同名,二者不代表同一对象,互不干扰。
- 注意末尾的“;”号必不可少。
struct [结构体名] { 类型标识符1 成员名1; 类型标识符2 成员名2; ... ... 类型标识符n 成员名n; };
struct student { char num[10]; /*学号*/ char name[20]; /*姓名*/ char sex; /*性别*/ int age; /*年龄*/ float score; /*分数*/ };
结构体的使用
struct Student
{
char name[50];
int age;
float score;
};
int main()
{
struct Student stu;
strcpy(stu.name,"name");
stu.age = 20;
stu.score = 85.5;
}
int main()
{
struct person
{
int year;
int age;
}p1,p2={2002,12};
printf("--%d\n",p2.year);
printf("--%d\n",p2.age);
retuen 0;
}
(二)用typedef定义结构体类型
typedef struct [结构体名]
{
类型标识符1 成员名1;
类型标识符2 成员名2;
... ...
类型标识符n 成员名n;
}新类型标识符
typedef struct student
{
char num[10]; /*学号*/
char name[20]; /*姓名*/
char sex; /*性别*/
int age; /*年龄*/
float score; /*分数*/
}STU;
STU zhangsan;//总有以上属性
zhangsan.age;
zhangsan.score;
三、结构体嵌套
struct birthday
{
int year;
int month;
int day;
};
struct person
{
char name[50];
int age;
struct birthday bir;
};
birthday 必须建立在 person 之前
如何访问到year呢?
结构体嵌套时应逐级引用
如果成员本身又是一个结构体,则必须逐级找到最低级的成员才能使用。stu1.birthday.month stu1.birthday.year stu1.birthday.day
同一种类型的结构体变量间可直接赋值
一般地,可以将一个结构体变量作为一个整体赋给另一个具有相同类型的结构体变量。
stu1=stu2 stu2.birthday=stu1.birthday
(逐层递进)
练习
【例】 计算一名学生的平均成绩。学生的信息包括学号、姓名、性别及C语言、VB程序设计、数据结构三门课程成绩,已知该学生的学号为:10001,姓名为:“WuHong”,性别为:‘F’,三门课程的成绩要求从键盘输入,最后输出学生的全部信息,并计算课程的平均成绩。
本例需要注意3个问题:
1、学生信息的输入不能整体进行,必须要对每一个成员分别进行输入。
2、成员的引用方式。
3、将“10001”赋值给学生的学号成员及将“WuHong”复制给学生的姓名成员时,不能直接使用“=”运算符,而应使用字符串赋值函数。
#include "stdafx.h"
#include <string.h>
struct student
{
char name[50];
char xb[10];
int xh;
int score_c;
int score_vb;
};
int _tmain(int argc, _TCHAR* argv[])
{
struct student stu;
strcpy(stu.name,"WuHong");
strcpy(stu.xb,"F");
stu.xh = 10001;
scanf("%d",&stu.score_c);
scanf("%d",&stu.score_vb);
printf("以下为学生的全部信息\n");
printf("学号是:%d\n",stu.xh);
printf("姓名:%s\n",stu.name);//%c输出字符,%c输出字符串,%d输出ASCII码值
printf("性别是:%s\n",stu.xb);
printf("c语言成绩为:%d\n",stu.score_c);
printf("vb的成绩是:%d\n",stu.score_vb);
return 0;
}
字符串可以用gets(),输出仍是%s
结构体与指针
看代码
struct stu2
{
int num;
char *name;
char banji[100];
char sex;
float score;
}s2={101,"lihong","sannian",'F',95.5};
printf("2.1----%d\n",s2.num);
printf("2.2----%s\n",s2.name);
printf("2.2.1----%s\n",s2.banji);
printf("2.3----%c\n",s2.sex);
printf("2.4----%f\n",s2.score);
printf("\n\n\n\n");
字符串指针可以用%s,s2.name存的是l的地址
struct stu2 *p1;//一个普通的变量,一个指向结构体的指针
p1 = &s2;
p1->num = 111;
p1->name = "11111";//name 为指针,直接等于字符串的地址~~~
strcpy(p1->banji,"wu");
(*p1).sex = 'm';
p1->score = 2.14;
*name指向l
lihong和sannian是字符串,用""
->指向符号,也可以理解成什么的什么
p->num,p的num
printf("3.1----%p\n",p1);
printf("3.1----%d\n",p1->num);
printf("3.1----%p\n",p1->name);
printf("3.1----%p\n",p1->banji);
printf("3.1----%p\n",(*p1).sex);
printf("3.1----%p\n",p1->score);
printf("\n\n\n\n");
%p是输出地址
*p是取地址里的值,所以(*p1).sex就相当于s2.sex
总览代码
struct stu2
{
int num;
char *name;
char banji[100];
char sex;
float score;
}s2={101,"lihong","sannian",'F',95.5};
printf("2.1----%d\n",s2.num);
printf("2.2----%s\n",s2.name);
printf("2.2.1----%s\n",s2.banji);
printf("2.3----%c\n",s2.sex);
printf("2.4----%f\n",s2.score);
printf("\n\n\n\n");
struct stu2 *p1;//一个普通的变量,一个指向结构体的指针
p1 = &s2;
p1->num = 111;
p1->name = "11111";//name 为指针,直接等于字符串的地址~~~
strcpy(p1->banji,"wu");
(*p1).sex = 'm';
p1->score = 2.14;
printf("3.1----%p\n",p1);
printf("3.1----%d\n",p1->num);
printf("3.1----%p\n",p1->name);
printf("3.1----%p\n",p1->banji);
printf("3.1----%p\n",(*p1).sex);
printf("3.1----%p\n",p1->score);
printf("\n\n\n\n");
三、结构体数组
结构体数组的每一个元素都是具有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等,结构数组的定义方法和结构变量相似,只需要说明它是数组类型即可。
2.结构体数组的初始化
(1)顺序初始化
按照数组中所有元素的所有成员的存储顺序进行初始化赋值。
struct student1 { char num[10]; char name[20]; char sex; int age; float score; }st1[3]={"11201","Wang Lin",'F',20,89, //st[0] "11202","Li Gang",'M',17,70, //st[1] "11203","Liu Yan",'F',19,90}; //st[2]
↑ 这种不建议使用 ↑
struct student2 { char num[10]; char name[20]; char sex; int age; float score; }st2[3]={{"11201","WangLin",'F',20,89}, //st[0] {"11202","Li Gang",'M',19,70}, //st[1] {"11203","Liu Yan",'F',19,90}}; //st[2]
↑ 用这种 ↑
(2)分行初始化
在对结构体数组进行初始化时,将每个数组元素的数据分别用花括弧括起来。
当对全部元素做初始化赋值时,可以不给出数组长度;若只给数组元素的部分成员数据进行初始化赋值,则需给出数组长度。
struct student3 { char num[10]; char name[20]; char sex; int age; float score; }st3[]={{"11201","WangLin",'F',20,89}, {"11202","Li Gang",'M',19,70}, {"11203","Liu Yan",'F',19,90}};
对全部元素初始化,可以不给出数组长度 struct student4 { char num[10]; char name[20]; char sex; int age; float score; }st4[3]={{"11201","Wang Lin",'F'}, {"11201","Li Gang",'M'}, {"11202","Liu Yan",'F'}};
上述语句中,数组st中的二个数组成员 age,score 均没有进行初始化赋值,只对其他的三个数值 num,name,sex 做了初始化赋值。因此必须给出数组长度。
char赋值注意事项
char a[10] = "string"; //可以
char a[10];a = "string"; //不可以,只能用strcpy
char *a = "string"; //可以
cahr *a;a = "string"; //可以
例题
有 以下程序段:
struct st {int x;int *y;}*pt; int a[]={1,2},b[]={3,4}; struct st c[2]={10,a,20,b}; pt=c;
以下选项中表达式的值为11的是()
A.++pt->x B.pt->x
C.*pt->y D.(pt++)->x
答案选A
c[0]里有int x和int *y,c[1]也是,所以按顺序赋值
训练
强化训练
题目
从键盘输入五个学生的信息看,包括:学号、姓名、性别、年龄和成绩,并统计这5位学生的平均年龄、平均成绩和不及格的人数
int main()
{
// 定义一个结构体数组来存储5位学生的信息
struct Student students[5];
int i;
int sum_age = 0; // 记录学生年龄总和
int sum_score = 0; // 记录学生成绩总和
int fail_count = 0; // 记录不及格人数
// 从键盘输入学生信息
for (i = 0; i < 5; i++)
{
printf("请输入第%d位学生的学号:", i + 1);
scanf("%d", &students[i].id);
printf("请输入第%d位学生的姓名:", i + 1);
scanf(" %s", students[i].name); // 注意空格,避免读取换行符等错误
printf("请输入第%d位学生的性别:", i + 1);
scanf(" %c", &students[i].gender); // 注意空格,避免读取换行符等错误
printf("请输入第%d位学生的年龄:", i + 1);
scanf("%d", &students[i].age);
printf("请输入第%d位学生的成绩:", i + 1);
scanf("%d", &students[i].score);
sum_age += students[i].age; // 累加年龄
sum_score += students[i].score; // 累加成绩
}
// 计算平均年龄和平均成绩
float avg_age = (float) sum_age / 5;
float avg_score = (float) sum_score / 5;
// 输出学生信息及统计结果
printf("\n学生信息如下:\n");
for (i = 0; i < 5; i++) {
printf("学号:%d,姓名:%s,性别:%c,年龄:%d,成绩:%d\n", students[i].id, students[i].name, students[i].gender, students[i].age, students[i].score);
if (students[i].score < 60) { // 不及格条件设定为成绩小于60分
fail_count++; // 不及格人数加1
}
}
printf("\n平均年龄:%.2f,平均成绩:%.2f,不及格人数:%d\n", avg_age, avg_score, fail_count);
return 0;
}