1、结构体
1、为什么需要结构体
为了表示一些复杂的事物,而普通的基本类型无法满足实际要。
2、求什么叫结构体
把一些基本类型数据组合在一起形成的一个新的复合数据类型,这个叫做结构体。
3、如何定义结构体
/*---------------------------------------------- 结构体的定义方式 ----------------------------------------------- 3种方式,推荐使用第一种: -----------------------------------------------*/ # include <stdio.h> //第一种方式 这只是定义了一个新的数据类型,并没有定义变量 struct Student { int age; float score; char sex; }; //第二种方式 struct Student2 { int age; float score; char sex; } st2; //第三种方式 struct { int age; float score; char sex; } st3; int main(void) { struct Student st = {80, 66.6, 'F'}; return 0; }
4、怎样使用结构体变量
赋值和初始化
定义的同时可以整体赋初值
如果定义完之后,则只能单个的赋初值
/*---------------------------------------------- 结构体变量的赋值和初始化 -----------------------------------------------*/ # include <stdio.h> //第一种方式 struct Student { int age; float score; char sex; }; int main(void) { struct Student st = {80, 66.6, 'F'}; //初始化 定义的同时赋初值 struct Student st2; st2.age = 10; st2.score = 88; st2.sex = 'F'; printf("%d %f %c\n", st.age, st.score, st.sex); //80 66.599998 F printf("%d %f %c\n", st2.age, st2.score, st2.sex); //10 88.000000 F return 0; }
5、如何取出结构体变量中的每一个成员【重点】
1) 结构体变量名.成员名
2) 指针变量名-〉成员名(第二种方式更常用)
指针变量名->成员名在计算机内部会被转化成(*指针变量名).成员名的方式来执行
所以说这两种方式是等价的
/*---------------------------------------------- 如何取出结构体变量中的每一个成员 -----------------------------------------------*/ # include <stdio.h> struct Student { int age; float score; char sex; }; int main(void) { struct Student st = {80, 66.6F, 'F'}; //初始化 定义的同时赋初值 struct Student * pst = &st; //&st不能改成st pst->age = 88;//第二种方式 st.score = 66.6f; //第一种方式 66.6在C语言中默认是double类型,如果希望一个实数是float类型,则必须在末尾加f或F,
//因此66.6是double, 66.6f或66.6F是float printf("%d %f\n", st.age, pst->score); //88 66.599998:因为浮点型数据不能保证每一个数字都能准确存储 return 0; } /*----------------------------------------------------------------------------------------------- 1.pst->age在计算机内部会被转化成(*pst).age,没有什么为什么,这就是一>的含义,这也是一种硬性规定 2.所以pst->age等价于(*pst).age也等价于st.age 3.我们之所以知道pst->age等价于st.age,是因为pst->age是被转化成了(*pst).age来执行 4.pst->age的含义: pst所指向的那个结构体变量中的age这个成员 ------------------------------------------------------------------------------------------------*/
6、结构体变量和结构体指针变量作为函数参数传递的问题
推荐使用结构体指针变量作为函数参数来传递
/* 通过函数完成对结构体变量的输入和输出 */ # include <stdio.h> # include <string.h> struct Student { int age; char sex; char name[100]; }; //分号不能省 void InputStudent(struct Student *); void OutputStudent(struct Student ss); int main(void) { struct Student st; //15行 InputStudent(&st); //对结构体变量输入 必须发送st的地址 // printf("%d %c %s\n", st.age, st.sex, st.name); OutputStudent(st); //对结构体变量输出 可以发送st的地址也可以直接发送st的内容 return 0; } void OutputStudent(struct Student ss) { printf("%d %c %s\n", ss.age, ss.sex, ss.name); //10 F 张三 } //pstu存放st的地址,*pstu就是st, (*pstu).age = 10等价于st.age=10 void InputStudent(struct Student * pstu) //pstu只占4个字节 { (*pstu).age = 10; strcpy(pstu->name, "张三"); pstu->sex = 'F'; } /* //本函数无法修改主函数15行st的值 所以本函数是错误的 void InputStudent(struct Student stu) { stu.age = 10; strcpy(stu.name, "张三"); //不能写成 stu.name = "张三"; stu.sex = 'F'; } */
/* 示例: 发送地址还是发送内容 目的: 指针的优点之一: 快速的传递数据, 耗用内存小 执行速度快 */ # include <stdio.h> # include <string.h> struct Student { int age; char sex; char name[100]; }; //分号不能省 void InputStudent(struct Student *); void OutputStudent(struct Student *); int main(void) { struct Student st ; //15行 //printf("%d\n", sizeof(st)); InputStudent(&st); //对结构体变量输入 必须发送st的地址 OutputStudent(&st); //对结构体变量输出 可以发送st的地址也可以直接发送st的内容 但为了减少内存的耗费,也为了提高执行速度,推荐发送地址 return 0; } void OutputStudent(struct Student *pst) { printf("%d %c %s\n", pst->age, pst->sex, pst->name); } void InputStudent(struct Student * pstu) //pstu只占4个字节 { (*pstu).age = 10; strcpy(pstu->name, "张三"); pstu->sex = 'F'; } /* //本函数无法修改主函数15行st的值 所以本函数是错误的 void InputStudent(struct Student stu) { stu.age = 10; strcpy(stu.name, "张三"); //不能写成 stu.name = "张三"; stu.sex = 'F'; } */
7、结构体变量的运算
结构体变量不能相加,不能想减,也不能相互乘除但结构体变量可以相互赋值。
struct Student { int age; char sex; char name[100]; }; struct Student st1,st2; //st1+st2 st1*st2 st1/st2都是错误的,st1=st2或者st2=st1都是正确的
# include <stdio.h> //冒泡排序 void sort(int * a, int len) { int i, j, t; for (i=0; i<len-1; ++i) { for (j=0; j<len-1-i; ++j) { if (a[j] > a[j+1]) // >表示升序 <表示降序 { t = a[j]; a[j] = a[j+1]; a[j+1] = t; } } } } int main(void) { int a[6] = {10, 2, 8, -8, 11, 0}; int i = 0; sort(a, 6); for (i=0; i<6; ++i) { printf("%d ", a[i]); } printf("\n"); return 0; }
8、动态构造存放学生信息的结构体数组
动态构造一个数组,存放学生的信息然后按分数排序输出。
# include <stdio.h> # include <malloc.h> struct Student { int age; float score; char name[100]; }; int main(void) { int len; struct Student * pArr; int i, j; struct Student t; //动态的构造一维数组 printf("请输入学生的个数:\n"); printf("len = "); scanf("%d", &len); pArr = (struct Student *)malloc(len * sizeof(struct Student)); //输入 for (i=0; i<len; ++i) { printf("请输入第%d个学生的信息:\n", i+1); printf("age = "); scanf("%d", &pArr[i].age); printf("name = "); scanf("%s", pArr[i].name); //name是数组名,本身就已经是数组首元素的地址, 所以pArr[i].name 不能改成 &pArr[i].name printf("score = "); scanf("%f", &pArr[i].score); } //按学生成绩升序排序 冒泡算法 for (i=0; i<len-1; ++i) { for (j=0; j<len-1-i; ++j) { if (pArr[j].score > pArr[j+1].score) //>升序 <降序 按分数比较 { //互换的不是成绩,而是整体位置 t = pArr[j]; pArr[j] = pArr[j+1]; pArr[j+1] = t; } } } printf("\n\n学生的信息是:\n"); //输出 for (i=0; i<len; ++i) { printf("第%d个学生的信息是:\n", i+1); printf("age = %d\n", pArr[i].age); printf("name = %s\n", pArr[i].name); //name是数组名,本身就已经是数组首元素的地址, 所以pArr[i].name 不能改成 &pArr[i].name printf("score = %f\n", pArr[i].score); printf("\n"); } return 0; } /*------------------------------- 请输入学生的个数: len = 3 请输入第1个学生的信息: age = 21 name = zhang score = 100 请输入第2个学生的信息: age = 20 name = bo score = 99 请输入第3个学生的信息: age = 21 name = hh score = 98 学生的信息是: 第1个学生的信息是: age = 21 name = hh score = 98.000000 第2个学生的信息是: age = 20 name = bo score = 99.000000 第3个学生的信息是: age = 21 name = zhang score = 100.000000 Press any key to continue --------------------------------------*/