赞
踩
目录
编程练习:输入两个学生的名字,学号,成绩等输出成绩高的学生的信息
为什么要引入结构体?
如果没有结构体的话就只能 int char float 单独去定义,不是一个有机的整体,利用结构体定义数据类型可以将这些数据都融合到一起,就可以模拟实现多一的数据类型。(类比数组,数组是相同的数据类型集合到一起,结构体是不同的数据类型集合到一起)
- /*
- 如何定义一个结构体
- */
-
- #include <stdio.h>
-
- struct Student //告知系统是一个结构体,关键字"struct"
- {
- int num;
- char name[32];
- char sex[4];
- char address[32];
- int age;
- double score;
- }; //分号很重要,不能丢
-
- struct Date
- {
- int year;
- int month;
- int day;
- int hour;
- int minute;
- int seconds;
- };
-
- int main()
- {
-
- return 0;
- }
- /*
- 结构体变量的定义和访问
- */
-
- #include <stdio.h>
- #include <string.h>
-
- struct Student
- {
- int num;
- char name[32];
- char sex[4];
- char address[32];
- int age;
- double score;
- };
-
- int main()
- {
- int a;
- struct Student stu1; //struct Student就相当于int
- struct Student stu2 = {20140678,"唔西迪兮","女","河北",18,97.5};
-
- stu1.num = 20140656; //点运算符来访问结构体中的成员变量(域)
- strcpy(stu1.name,"玛卡巴卡"); //给字符串赋值用字符串拷贝
- strcpy(stu1.sex,"男");
- strcpy(stu1.address,"山西");
- stu1.age = 18;
- stu1.score = 98.5;
-
- printf("学号:%d 姓名:%s 性别:%s 地址:%s 年龄:%d 分数:%.1lf\n",
- stu1.num,stu1.name,stu1.sex,stu1.address,stu1.age,stu1.score);
-
- printf("学号:%d 姓名:%s 性别:%s 地址:%s 年龄:%d 分数:%.1lf\n",
- stu2.num,stu2.name,stu2.sex,stu2.address,stu2.age,stu2.score);
-
- return 0;
- }
- /*
- 输入两个学生的名字,学号,成绩等输出成绩高的学生的信息
- */
-
-
- #include <stdio.h>
-
- struct Student
- {
- int num;
- char name[32];
- char sex[4];
- char address[32];
- int age;
- double score;
- };
-
- int main()
- {
- struct Student stu1;
- struct Student stu2;
- struct Student Better;
-
- printf("请输入学生1的学号、姓名、性别、地址、年龄、分数\n");
- scanf("%d%s%s%s%d%lf",&stu1.num,stu1.name,stu1.sex,stu1.address,&stu1.age,&stu1.score);
-
- printf("请输入学生2的学号、姓名、性别、地址、年龄、分数\n");
- scanf("%d%s%s%s%d%lf",&stu2.num,stu2.name,stu2.sex,stu2.address,&stu2.age,&stu2.score);
-
- printf("学生1的成绩:%.1lf 学生2的成绩:%.1lf\n",stu1.score,stu2.score);
-
- Better = stu1;
-
- if(stu1.score < stu2.score)
- {
- Better = stu2;
- }
-
- puts("成绩较好的是");
- printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
- Better.num,Better.name,Better.sex,Better.address,Better.age,Better.score);
-
- return 0;
- }
它与前面讲的数值型数组几乎是一模一样的,只不过需要注意的是,结构体数组的每一个元素都是一个结构体类型的变量,都包含结构体中所有的成员项。
定义结构体数组的方法很简单,同定义结构体变量是一样的,只不过将变量改成数组。或者说同前面介绍的普通数组的定义是一模一样的,如:
struct Student stu[10];
这就定义了一个结构体数组,共有 10 个元素,每个元素都是一个结构体变量,都包含所有的结构体成员。
结构体数组的引用与引用一个结构体变量在原理上是一样的。只不过结构体数组中有多个结构体变量,我们只需利用 for 循环来遍历结构体数组中的元素。
- /*
- 结构体数组应用
- */
-
-
- #include <stdio.h>
-
- struct Student
- {
- int num;
- char name[32];
- char sex[4];
- char address[32];
- int age;
- double score;
- };
-
- int main()
- {
- struct Student stu[3] = {
- {20140656,"玛卡巴卡","男","山西",18,98.5},
- {20140678,"唔西迪兮","女","河北",18,97.5},
- {20140690,"依古比古","男","北京",18,95.5}
- };
-
- int i;
- int len = sizeof(stu)/sizeof(stu[0]);
-
- for(i=0;i<len;i++)
- {
- printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
- stu[i].num,stu[i].name,stu[i].sex,stu[i].address,stu[i].age,stu[i].score);
- }
-
-
- return 0;
- }
- /*
- 选票系统
- */
-
- #include <stdio.h>
- #include <string.h>
-
- struct Voter
- {
- int tickets;
- char name[32];
- };
-
- int main()
- {
- struct Voter xm[3];
- struct Voter Best;
-
- int i;
- int len = sizeof(xm)/sizeof(xm[0]);
- int total = 6; //总票数为6
- char tempname[32]; //定义一个临时名字来和选民的名字一一对比,相同的对应的票数加1
- int j;
- int mark = 0;
- int abandon = 0;
-
- //初始化环节
- for(i=0;i<len;i++)
- {
- xm[i].tickets = 0;
- printf("请输入第%d位选民的名字\n",i+1);
- scanf("%s",xm[i].name);
- }
- //唱票环节
- for(i=0;i<total;i++)
- {
- mark = 0;
- printf("请问你想投给谁?\n");
- memset(tempname,'\0',sizeof(tempname)); //每次投票时,临时名字都清空成0
- scanf("%s",tempname);
- for(j=0;j<len;j++)
- {
- if(strcmp(tempname,xm[j].name) == 0)
- { //将每次的投票和选民的名字进行对比,如果相同,对应的票数加1,如果不一样,则弃票
- xm[j].tickets++;
- mark = 1;
- }
- }
- if(mark == 0) //如果投票和所有名字都不匹配,弃票加1
- {
- printf("弃票\n");
- abandon++;
- }
- }
-
- //公布环节
-
- for(i=0;i<len;i++)
- {
- printf("name:%s tickets:%d\n",xm[i].name,xm[i].tickets);
- }
-
- putchar('\n');
-
- Best = xm[0];
-
- for(i=0;i<len;i++)
- {
- if(Best.tickets < xm[i].tickets)
- {
- Best = xm[i];
- }
- }
- printf("经投票,%s以%d票当选,弃票%d票\n",Best.name,Best.tickets,abandon);
-
- return 0;
- }
变量的访问有两种方式:1.变量名访问;2.通过地址来访问,结构体也一样,可以通过变量名和地址来访问结构体变量,因此引入结构体指针。
- /*
- 结构体指针的定义和应用
- */
-
- #include <stdio.h>
-
- struct Test
- {
- int indata;
- char cdata;
- };
-
- int main()
- {
- int idata = 10;
- int *pi = &idata; //之前定义指针的方法
-
- char cdata = 'R';
- char *pc = &cdata; //之前定义指针的方法
-
- struct Test T1 = {20,'E'};
- struct Test *pt = &T1;
-
- printf("indata = %d,cdata = %c\n",T1.indata,T1.cdata);
- //之前学到的用变量名访问结构体变量方法
-
- printf("indata = %d,cdata = %c\n",pt->indata,pt->cdata);
- //用结构体指针访问结构体变量的方法,用"->"取代点运算符
- return 0;
- }
- /*
- 用结构体指针来遍历数组
- */
-
- #include <stdio.h>
-
- struct Student
- {
- int num;
- char name[32];
- char sex[4];
- char address[32];
- int age;
- double score;
- };
-
- int main()
- {
- struct Student stu[3] = {
- {20140656,"玛卡巴卡","男","山西",18,98.5},
- {20140678,"唔西迪兮","女","河北",18,97.5},
- {20140690,"依古比古","男","北京",18,95.5}
- };
- struct Student *p;
- p = stu;
- int i;
- int len = sizeof(stu)/sizeof(stu[0]);
-
- for(i=0;i<len;i++)
- {
- printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
- p->num,p->name,p->sex,p->address,p->age,p->score);
- p++;
- }
-
- /* 使用指针遍历数组时,一次遍历指针会移到数组的尾巴,
- 所以当要再一次遍历时,要重新指向数组的首地址。
- p = stu;
-
- for(i=0;i<len;i++)
- {
- printf("num:%d name:%s sex:%s address:%s age:%d score:%.1lf\n",
- p->num,p->name,p->sex,p->address,p->age,p->score);
- p++;
- }*/
-
-
-
- return 0;
- }
注意:如果使用结构体指针遍历数组后想要再次遍历数组的时候,要把指针再次指向数组首地址!!!要不然就会出现以下等问题:
- /*
- 用结构体指针改写选票系统
- */
-
-
- #include <stdio.h>
- #include <string.h>
-
- struct Voter
- {
- int tickets;
- char name[32];
- };
-
- /*
- 1.把以前普通的变量名或者下标访问的运算符,改成结构体指针的 "->"
- 2.每次遍历数组都会指针都会偏移到数组尾巴,下次遍历之前要重新指向数组首地址
- */
-
- int main()
- {
- struct Voter xm[3];
- struct Voter Best;
- struct Voter *p;
- p = xm;
-
- int i;
- int len = sizeof(xm)/sizeof(xm[0]);
- int total = 6; //总票数为6
- char tempname[32]; //定义一个临时名字来和选民的名字一一对比,相同的对应的票数加1
- int j;
- int mark = 0;
- int abandon = 0;
-
- //初始化环节
- for(i=0;i<len;i++)
- {
- p->tickets = 0;
- printf("请输入第%d位选民的名字\n",i+1);
- scanf("%s",p->name);
- p++;
- }
- //唱票环节
- p = xm;
- for(i=0;i<total;i++)
- {
- mark = 0;
- printf("请问你想投给谁?\n");
- memset(tempname,'\0',sizeof(tempname)); //每次投票时,临时名字都清空成0
- scanf("%s",tempname);
- p = xm;
- for(j=0;j<len;j++)
- {
- if(strcmp(tempname,p->name) == 0)
- { //将每次的投票和选民的名字进行对比,如果相同,对应的票数加1,如果不一样,则弃票
- p->tickets++;
- mark = 1;
- }
- p++;
- }
- if(mark == 0) //如果投票和所有名字都不匹配,弃票加1
- {
- printf("弃票\n");
- abandon++;
- }
- }
-
- //公布环节
- p = xm;
- for(i=0;i<len;i++)
- {
- printf("name:%s tickets:%d\n",p->name,p->tickets);
- p++;
- }
-
- putchar('\n');
-
- Best = xm[0];
- p = xm;
- for(i=0;i<len;i++)
- {
- if(Best.tickets < p->tickets)
- {
- Best = *p;
- }
- p++;
- }
- printf("经投票,%s以%d票当选,弃票%d票\n",Best.name,Best.tickets,abandon);
-
- return 0;
- }
- /*
- 结构体指针数组函数综合应用改写选票系统
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- struct Voter
- {
- int tickets;
- char name[32];
- };
-
- struct Voter *InitFun(struct Voter *p,int *len)
- {
- int i;
-
- if(p == NULL)
- {
- printf("请输入有几个人参选?\n");
- scanf("%d",len);
- p = (struct Voter *)malloc(*len * sizeof(struct Voter));
- }
-
- for(i=0;i<*len;i++)
- {
- p->tickets = 0;
- printf("请输入第%d位选民的名字\n",i+1);
- scanf("%s",p->name);
- p++;
- }
- return p-*len;
- }
-
- void PrintFun(struct Voter *p,int len)
- {
- int i;
- for(i=0;i<len;i++)
- {
- printf("name:%s tickets:%d\n",p->name,p->tickets);
- p++;
- }
- }
-
- int CallFun(struct Voter *p,int len)
- {
- int i;
- int total = 0;
- char tempname[32];
- int j;
- int mark = 0;
- int abandon = 0;
- struct Voter *pback = p;
-
- printf("请问总共有多少人投票?\n");
- scanf("%d",&total);
-
- for(i=0;i<total;i++)
- {
- mark = 0;
- printf("请输入你想投给谁?\n");
- memset(tempname,'\0',sizeof(tempname));
- scanf("%s",tempname);
- p = pback;
- for(j=0;j<len;j++)
- {
- if(strcmp(tempname,p->name) == 0)
- {
- p->tickets++;
- mark = 1;
- }
- p++;
- }
- if(mark == 0)
- {
- printf("弃票\n");
- abandon++;
- }
- }
- return abandon;
- }
-
- struct Voter *GetBest(struct Voter *p,int len)
- {
- int i;
- struct Voter *Best;
-
- Best = p;
-
- for(i=0;i<len;i++)
- {
- if(Best->tickets < p->tickets)
- {
- Best = p;
- }
- }
- return Best;
- }
-
- int main()
- {
- struct Voter *xm = NULL;
- int len = 0;
-
- xm = InitFun(xm,&len);
- PrintFun(xm,len);
-
- int abandon = CallFun(xm,len);
- PrintFun(xm,len);
-
- struct Voter *Best = GetBest(xm,len);
-
- printf("%s以%d票当选,弃票%d票\n",Best->name,Best->tickets,abandon);
-
- return 0;
- }
假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,它们的关系如下图所示:
将这种关系转换为C语言代码:
指针变量也是一种变量,也会占用存储空间,也可以使用&
获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*
。p1 是一级指针,指向普通类型的数据,定义时有一个*
;p2 是二级指针,指向一级指针 p1,定义时有两个*
。(结构体的二级指针也一样)
- /*
- 结构体二级指针应用
- */
-
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- struct Voter
- {
- int tickets;
- char name[32];
- };
-
- struct Voter *InitFun(struct Voter **p,int *len)
- {
- int i;
-
- if(*p == NULL)
- {
- printf("请输入有几个人参选?\n");
- scanf("%d",len);
- *p = (struct Voter *)malloc(*len * sizeof(struct Voter));
- }
-
- for(i=0;i<*len;i++)
- {
- (*p)->tickets = 0; //当二级指针的"*"和"->"运算符在一起的时候要括起来注意符号优先级问题
- printf("请输入第%d位选民的名字\n",i+1);
- scanf("%s",(*p)->name);
- (*p)++;
- }
- return *p - *len;
- }
-
- void PrintFun(struct Voter *p,int len)
- {
- int i;
- for(i=0;i<len;i++)
- {
- printf("name:%s tickets:%d\n",p->name,p->tickets);
- p++;
- }
- }
-
- int CallFun(struct Voter *p,int len)
- {
- int i;
- int total = 0;
- char tempname[32];
- int j;
- int mark = 0;
- int abandon = 0;
- struct Voter *pback = p;
-
- printf("请问总共有多少人投票?\n");
- scanf("%d",&total);
-
- for(i=0;i<total;i++)
- {
- mark = 0;
- printf("请输入你想投给谁?\n");
- memset(tempname,'\0',sizeof(tempname));
- scanf("%s",tempname);
- p = pback;
- for(j=0;j<len;j++)
- {
- if(strcmp(tempname,p->name) == 0)
- {
- p->tickets++;
- mark = 1;
- }
- p++;
- }
- if(mark == 0)
- {
- printf("弃票\n");
- abandon++;
- }
- }
- return abandon;
- }
-
- struct Voter *GetBest(struct Voter *p,int len)
- {
- int i;
- struct Voter *Best;
-
- Best = p;
-
- for(i=0;i<len;i++)
- {
- if(Best->tickets < p->tickets)
- {
- Best = p;
- }
- }
- return Best;
- }
-
- int main()
- {
- struct Voter *xm = NULL;
- int len = 0;
-
- xm = InitFun(&xm,&len);
- PrintFun(xm,len);
-
- int abandon = CallFun(xm,len);
- PrintFun(xm,len);
-
- struct Voter *Best = GetBest(xm,len);
-
- printf("%s以%d票当选,弃票%d票\n",Best->name,Best->tickets,abandon);
-
- return 0;
- }
共用体和结构体十分相似,是一种构造类型或复杂类型,它也可以包含多个类型不同的成员。
结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
注意:结构体占用的内存大于等于所有成员占用的内存的总和(成员之间可能会存在缝隙),共用体占用的内存等于最长的成员占用的内存。共用体使用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,就会把原来成员的值覆盖掉。
- /*
- 共用体的定义及其注意事项
- */
-
- #include <stdio.h>
-
- struct TestT
- {
- int indata;
- char cdata;
- double ddata;
- };
-
- union TestU
- {
- int indata;
- char cdata;
- };
-
- int main()
- {
- struct TestT t1;
- union TestU u1;
-
- t1.indata = 10;
- t1.cdata = 'c';
- t1.ddata = 98.5;
-
- u1.indata = 10;
- u1.cdata = 'd';
-
- printf("结构体大小是sizeof = %d\n",sizeof(t1)); //内存大于或等于所有成员的内存
- printf("共用体大小是sizeof = %d\n",sizeof(u1)); //内存大小由最大成员的内存决定
-
- printf("结构体:\n indata:%p %d\n cdata:%p %d\n ddata:%p %d\n",t1.indata,t1.cdata,t1.ddata);
- //结构体成员的每一个都有单独的地址
- printf("共用体:\n indata:%p %d\n cdata:%p\n ",u1.indata,u1.cdata);
- //共用体所有成员都共用一个地址
-
-
- //因为结构体成员每一个都有独立的内存空间,所以它的每一个成员都可以打印出来。互不干扰;
- //因为共用体成员每一个都是公用同一个内存空间,所以它的值会被之后一个输入的成员覆盖掉。
- return 0;
- }
- /*
- 共用体应用
- */
-
-
- #include <stdio.h>
-
- struct Person
- {
- char name[32];
- int num;
- char sex[4];
- char Profession;
- union
- {
- char class[8];
- char subject[4];
- }mes;
- };
-
- int main()
- {
- struct Person p[2];
- int i;
- int len = sizeof(p)/sizeof(p[0]);
-
- for(i=0;i<len;i++)
- {
- printf("请输入您的职业,t or s\n");
- scanf("%c",&(p[i].Profession));
- if(p[i].Profession == 't')
- {
- printf("请老师输入名字\n");
- scanf("%s",p[i].name);
- printf("请老师输入所教的科目\n");
- scanf("%s",p[i].mes.subject);
- }
- else
- {
- printf("请学生输入名字\n");
- scanf("%s",p[i].name);
- printf("请学生输入所在班级\n");
- scanf("%s",p[i].mes.class);
- }
- getchar();
- }
-
- for(i=0;i<len;i++)
- {
- if(p[i].Profession == 't')
- {
- printf("老师的名字是%s,所教的科目是%s\n",p[i].name,p[i].mes.subject);
- }
- else
- {
- printf("学生的名字是%s,所在班级是%s\n",p[i].name,p[i].mes.class);
- }
- }
-
- return 0;
- }
在实际编程中,有些数据的取值往往是有限的,只能是非常少量的整数,并且最好为每个值都取一个名字,以方便在后续代码中使用,比如一个星期只有七天,一年只有十二个月,一个班每周有六门课程,这时候就要用到枚举类型。
- /*
- 枚举类型
- */
-
- #include <stdio.h>
-
- enum Month
- {
- Jan = 1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec
- }m1,m2;
-
- int main()
- {
-
- m1 = Feb;
- m2 = Dec;
-
- if(m1 < m2)
- {
- printf("我看你是在为难我玛卡巴卡\n");
- }
-
- printf("m1 = %d m2 = %d\n",m1,m2);
-
-
- return 0;
- }
-
- /*
- 1.值默认从0开始,枚举元素不能被赋值,虽然瞅着象变量名
- 2.可以指定列表中枚举数的值
- 3.可以直接忽略枚举类型名,直接定义枚举变量
- */
C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等。一旦用户在程序中定义了自己的数据类型名称,就可以在该程序中用自己的数据类型名称来定义变量的类型、数组的类型、指针变量的类型与函数的类型等。(方便用户使用)
- #include <stdio.h>
-
- typedef struct
- {
- int num;
- char name[32];
- char sex;
- }S,*p;
-
- void print1(S p)
- {
- printf("num:%d name:%s sex:%c\n",p.num,p.name,p.sex);
- }
-
- void print2(S *p)
- {
- printf("num:%d name:%s sex:%c\n",p->num,p->name,p->sex);
- }
-
- int main()
- {
- S p1 = {20140656,"玛卡巴卡",'b'};
- S p2 = {20140678,"唔西迪兮",'g'};
-
- print1(p1);
- print1(p2);
-
- S *pp1 = &p1;
- S *pp2 = &p2;
- print2(&p1);
- print2(&p2);
-
-
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。