一、为什么需要结构体?
为了表示复杂的事物,而一些普通的基本类型无法满足需求
二、什么是结构体
把一些基本类型数据组合在一起形成的一个新的复合数据类型
三、如何定义结构体(3种,只推荐使用其中一种)
#include <stdio.h>
#第一种方式
struct Student {
int age;
float score;
char sex;
};
#第二种方式:定义结构体的同时定义变量名,意味着只能定义一次,不好
#并且只有在定义时才能用 = { }方式赋值
typedef struct Student2 {
int age;
float score;
char sex;
} st2, st3;
#第三种方式:不知道变量类型,只知道变量名
struct {
int age;
float score;
char sex;
} st4, st5;
#第四种,给结构体变量类型起别名
typedef struct People {
char name[200];
int age;
double score;
} Person;
int main(void) {
int i = 10;
struct Student st = {22,100.0,'f'};
printf("%d\n",i);
return 0;
struct People p0 = {"小超", 22, 100.0};
Person p1 = {"小超", 22, 100.0};
st2.age = 10;
st2. sex = 'f';
}
四、怎样使用结构体变量
- 赋值和初始化
(1)定义的同时可以整体赋初始值
(2)如果定义完后只能单个属性赋值
#include <stdio.h>
struct Student {
int age;
float score;
char sex;
};
int main(void) {
int i = 10;
struct Student st = {22,100.0,'f'};
struct Student st2;
//st2 = {22,100.0,'f'}; //这样写是❌的,不可以只能在定义时这样写
st2.age = 20;
st2.score = 99.9;
st2.sex = 'm';
printf("%d %f %c\n", st1.age, st1.score, st1.sex);
printf("%d %f %c\n", st2.age, st2.score, st2.sex);
printf("%d\n",i);
return 0;
}
- 如何取出结构体变量中的每一个成员
(1) 结构体变量名.成员变量名
(2) 指针变量 -> 成员变量名 (更常用)
- pst -> age 在内部会被转化为(*pst).age,没为什么,这就是 ->的含义,硬性规定。所以 pst -> age = (*pst).age = st.age
浮点数float和double都不能保证每一个数字数据的准确存储。其编码格式导致:IE754标准导致了无法准确存储,只能存储一个近视值。
#include <stdio.h>
struct Student {
int age;
float score;
char sex;
char name[100];
};
int main(void) {
struct Student st = {22,100.0f,'f',"小超"};
st.age = 20; //第一种方式:结构体变量.成员变量
st.score = 66.6f; //浮点数float和double都不能保证数据的准确存储
struct Student * pst = &st;
pst -> age = 22; //第二种方式:指针变量 -> 成员变量
printf("%d %f %c %s \n",st.age, st.score, st.sex, st.name);
printf("%d %f %c %s \n",pst -> age, pst -> score, pst -> sex, pst -> name);
return 0;
}
- 结构体变量的运算
结构体变量之间不能 加 减 乘 除(➕ ➖ ✖️ ➗), 只能赋值=
- 结构体变量和结构体变量指针作为函数参数传递的问题
#include <stdio.h>
#include <string.h>
struct Student {
int age;
char sex;
double score;
char name[100];
};
void InputStudent(struct Student * st);
void OutputStudent(struct Student st);
int main(void) {
struct Student st = {22,'m',22.2,"hello world"};
OutputStudent(st);
InputStudent(&st);
OutputStudent(st);
printf("%d %d \n " sizeof(st), sizeof(&st));
return 0;
}
//需要修改变量的值,所以必须使用指针变量
void InputStudent(struct Student * st) { //st是保存4个字节的地址变量
st -> age = 30;
st -> sex = 'f';
st -> score = 100.0;
strcpy(st -> name , "world hello"); //字符串变量修改,不能用赋值符号 =
}
/*
只输出,不修改值,所以用不用指针无所谓。
但是为了减少内存的使用 和 执行速度,一般会使用指针的方式
缺点是不安全,C++及Java中使用const关键字使其不可修改
推荐发送地址,而不是变量
*/
void OutputStudent(struct Student st) {
printf("%d %c %lf %s\n", st.age, st.sex, st.score, st.name);
}
Java中const关键字告诉你可以发生地址,但是不能修改。
学数据结构,就是学数据的存储和操作。要学数据结构,必须学指针,不懂指针,就学不会数据结构。
- 举例:动态构造存放学生信息的结构体数组
# include <stdio.h>
# include <malloc.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 arr[5] = {10, 6, 8, -5, 4};
sort(arr, 5);
for(int i = 0; i < 5; i++) {
printf("%d\n",arr[i]);
}
return 0;
}
动态构造一个数组,存放学生的信息
然后按分数排序输出
#include <stdio.h>
#include <malloc.h>
struct Student {
int age;
double score;
char name[100];
};
int main(void) {
int len, i,j;
struct Student * pArr;
struct Student t;
printf("请输入学生的个数:\n");
printf("len = ");
scanf("%d", &len);
//动态构造一维数组,len是数组长度,pArr指向数组第一个元素的地址,元素类型是struct Student
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是数组名,本身已经是数组首元素地址,所以不需要取地址符
printf("score = ");
scanf("%lf",&pArr[i].score);
printf("\n");
}
//冒泡排序
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是数组名,本身已经是数组首元素地址,所以不需要取地址符
printf("score = %lf\n",pArr[i].score);
}
return 0;
}
- 链表
网友评论