结构体
为什么 需要结构体
为了表示一些复杂的事物,而普通的基本类型无法满是实际要求。
什么是 结构体
把一些 基本类型数据 组合 在一起形成的一个新的复合数据类型,这个叫做结构体。
如何 定义结构体
推荐第一种
// 第一种方式
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(){
struct Student st = {80, 66.6, 'F'};
return 0;
}
赋值 和 初始化
定义的同时可以整体贼初值
如果定义完之后,則只能单个的感初值
#include <stdio.h>
#include <stdlib.h>
// 第一种方式
struct Student{
int age;
float score;
char sex;
};
int main(){
// 第一种: 定义的同时, 完成赋值
struct Student st = {80, 66.6, 'F'}; // 初始化 定义的同时赋值
// 第二种: 定义完之后, 再赋值
struct Student st2;
st2.age = 10;
st2.score = 88;
st2.sex = 'F';
printf("%d %.2f %c\n", st.age, st.score, st.sex);
printf("%d %.2f %c\n", st2.age, st2.score, st2.sex);
return 0;
}
如何取出 结构体变量中 的 每一个成员
结构体变量名.成员名
指针变量名->成员名
一
st2.age = 10;
st2.score = 88;
st2.sex = 'F';
二
#include <stdio.h>
#include <stdlib.h>
struct Student{
int age;
float score;
char sex;
};
int main(){
struct Student st = {80, 66.6, 'F'};
struct Student* pst = &st;
pst->age = 88; // 第二种方式
st.age = 10; // 第一种方式
return 0;
// pst->age 在计算机内部会被转化成 (*pst).age
}
pst->age 等价于 (*pst).age 等价于 st.age
我们之所以知道pst->age等价于 st.age,
是因为pst->age是被转化成了 (*pgt).age来执行
指针变量名->成员名在计算机内部会被转化成
(*指针变量名).成员名
的方式来执行 所以说这两种方式是等价的
pst->age 表示 pst 所指向那个结构体变量中age这个成员
结构体变量 和 结构体变量指针 作为函数参数传递的问题
推荐使用 结构体指针变量 作为 函数参数 进行传递
动态构造存放学生信息的结构体数组
struct Student{
int age;
char sex;
char name[100]; //char类型占用1个字节,一个汉字占用2个字节,加[100]是为了储存足够多的汉字
};
int main(){
struct Student st = {20,'F',"小川"};
struct Student * pst = &st;
printf("%d %c %s\n", st.age, st.sex, st.name);
printf("%d %c %s\n", pst->age, pst->sex, pst->name);
}
指针拥有一个非常显著的优点
就是它 传递数据的速度 非常快
指针的优点之一:
快連的传递数据, 粍用内存小
执行連度快
/**
通过函数,完成对结构体的 输入 和 输出
*/
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
struct Student{
int age;
char sex;
char name[100]; //char类型占用1个字节,一个汉字占用2个字节,加[100]是为了储存足够多的汉字
};
void InputStudent(struct Student * stu){
// stu->age = 10;
(*stu).age = 10;
// strcpy的作用是将"张三"复制到stu.name中去
strcpy(stu->name, "张三"); // 不能写成 stu.name = "张三";
}
void OutputStudent(struct Student st){ // 可 地址 可 内容
printf("%d %c %s\n", st.age, st.sex, st.name);
}
int main(){
struct Student st;
InputStudent(&st); // 对 结构体变量 输入
OutputStudent(st); // 对 结构体变量 输出
return 0;
}
为了减少内存的耗费,减少速度,建议采用 指针 作为 参数 传入其中。
结构体运算
拓展
三大部分:
数据 存储 + 操作 + 输出
存储最难,就是数据结构
输出最简单,就是展示给用户看的。
数据存储,将 复杂的数据 进行存储。
复杂数据的存储, 里面一定会有指针的影子,or干脆就是指针的存在。
字符串末尾一定是 \0结尾。
冒泡排序
#include <stdio.h>
void sort(int * a, int len){
int i, j, t;
for (i = 0; i < len; ++i) {
for (j = 0; j < len - i - 1; j++) {
if (a[j] > a[j+1]) {
t = a[j];
a[j] = a[j+1];
a[j+1] = t;
}
}
}
}
int main(){
int a[6] = {10,2,8,-8,11,0};
int i;
sort(a, 6);
for (i = 0; i < 6; ++i) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
动态构造数组,存放学生信息,按分数排序输出
完成输入 和 输出
#include <stdio.h>
#include <stdlib.h>
struct Student{
char name[100];
int age;
float score;
};
int main(){
int len;
struct Student * pArr;
int i;
printf("请输入学生的个数:\n");
printf("len = ");
scanf("%d", &len);
// 动态的构造一维数组
pArr = (struct Student *)malloc(len * sizeof(struct Student));
// 输入学生信息
for (i = 0; i < len; ++i) {
printf("请输入第%d个学生的信息: ", i+1);
printf("age = ");
scanf("%d", &pArr[i].age);
printf("name = ");
scanf("%s",pArr[i].name); // 这里不能加&符号,因为 name本身就是 元素首地址了
// 数组名是第一元素的地址,&a == a[0]第一元素的地址
// pArr == a,所以写出pArr。就意味着找到了第一个元素的地址,直接取出来就行
printf("score = ");
scanf("%f",&pArr[i].score);
}
printf("\n\n学生的信息是:\n");
// 输出
for (i = 0; i < len; ++i) {
printf("第%d个学生的信息: ", i+1);
printf("age = %d\n",pArr[i].age);
printf("name = %s \n",pArr[i].name);
printf("score = %f\n",pArr[i].score);
}
return 0;
}
增加排序
#include <stdio.h>
#include <stdlib.h>
struct Student{
char name[100];
int age;
float score;
};
int main(){
int len;
struct Student * pArr;
int i;
int j;
struct Student temp;
printf("请输入学生的个数:\n");
printf("len = ");
scanf("%d", &len);
// 动态的构造一维数组
pArr = (struct Student *)malloc(len * sizeof(struct Student));
// 输入学生信息
for (i = 0; i < len; ++i) {
printf("请输入第%d个学生的信息: ", i+1);
printf("age = ");
scanf("%d", &pArr[i].age);
printf("name = ");
scanf("%s",pArr[i].name); // 这里不能加&符号,因为 name本身就是 元素首地址了
// 数组名是第一元素的地址,&a == a[0]第一元素的地址
// pArr == a,所以写出pArr。就意味着找到了第一个元素的地址,直接取出来就行
printf("score = ");
scanf("%f",&pArr[i].score);
}
// 排序
for (i = 0; i < len - 1; ++i) {
for (j = 0; j < len - i - 1; ++j) {
if (pArr[j].score > pArr[j+1].score){
temp = pArr[j];
pArr[j] = pArr[j + 1];
pArr[j+1] = temp;
}
}
}
printf("\n\n学生的信息是:\n");
// 输出
for (i = 0; i < len; ++i) {
printf("第%d个学生的信息: ", i+1);
printf("age = %d\n",pArr[i].age);
printf("name = %s \n",pArr[i].name);
printf("score = %f\n",pArr[i].score);
}
free(pArr);
return 0;
}