结构体
为什么需要结构体
为了表示一些复杂的事物,而普通的基本类型无法满足实际要求
什么叫结构体
把一些基本类型数据组合在一起形成的一个新的复合数据类型,这个叫做结构体
如何定义一个结构体
3种方式(推荐第一种)
//第一种方式 ,一般用第一种
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;
怎么使用结构体变量
赋值和初始化
定义的同时可以整体赋初值
如果定义完之后,则只能单个的赋初值
# 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 ",st.age,st.score,st.sex); printf("%d %f %c ",st2.age,st2.score,st2.sex); }
如何取出结构体变量中的每一个成员
1.结构体变量名.成员名
2.指针变量->成员名
指针变量->成员名 在计算机内部会被转化成(*指针变量名).成员名的方式来执行,所以说这两种方式是等价的
# include <stdio.h> struct Student { int age; float score; char sex; }; int main(void) { struct Student st = {80,66.6,'F'}; struct Student * pst = &st; //&st不能改成st pst->age = 88;//第二种方式 st.age;//第一种方式 return 0; }
1.pst->age 在计算机内部会被转化成(*pst).age
2.所以pst->age 等价于 (*pst).age 也等价于 st.age
3.pst->age的含义:
pst所指向的那个结构体变量中的age这个成员
# 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转换为float类型,原本66.6是double类型 printf("%d %f ",st.age,pst->score); return 0; }
结构体变量和结构体指针变量作为函数参数传递的问题
推荐使用结构体指针变量作为函数参数来传递
/* 2009年11月24日9:17:43 通过函数完成对结构体变量的输入和输出 */ # 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 ", st.age, st.sex, st.name); OutputStudent(st); //对结构体变量输出 可以发送st的地址也可以直接发送st的内容 return 0; } void OutputStudent(struct Student ss)//不需要修改st,内容只是输出,所以指针可有可无 { printf("%d %c %s ", ss.age, ss.sex, ss.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'; } */
示例:
发送地址还是发送内容
目的:
指针的优点之一:
快速的传递数据
耗用内存小
执行速度快
/* 2009年11月24日9:17:43 示例: 发送地址还是发送内容 目的: 指针的优点之一: 快速的传递数据, 耗用内存小 执行速度快 */ # 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 ", sizeof(st)); InputStudent(&st); //对结构体变量输入 必须发送st的地址 OutputStudent(&st); //对结构体变量输出 可以发送st的地址也可以直接发送st的内容 但为了减少内存的耗费,也为了提高执行速度,推荐发送地址 return 0; } void OutputStudent(struct Student *pst) { printf("%d %c %s ", 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'; } */
结构体变量的运算
结构体变量不能相加,不能相减,也不能相互乘除
但结构体变量可以相互赋值
举例
动态构造存放学生信息的结构体数组
动态构造一个数组,存放学生的信息,然后按分数排序输出
# 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("请输入学生的个数: "); 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是数组名,本身就已经是数组首元素的地址, 所以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(" 学生的信息是: "); //输出 for (i=0; i<len; ++i) { printf("第%d个学生的信息是: ", i+1); printf("age = %d ", pArr[i].age); printf("name = %s ", pArr[i].name); //name是数组名,本身就已经是数组首元素的地址, 所以pArr[i].name 不能改成 &pArr[i].name printf("score = %f ", pArr[i].score); printf(" "); } return 0; }
枚举
什么是枚举
把一个事物所有可能的取值一一列举出来
怎样使用枚举
# include <stdio.h> //只定义了一个数据类型,并没有定义变量,该数据类型的名字是enum WeekDay enum WeekDay { MonDay,TuesDay,WednesDay,ThursDay,FriDay,SaturDay,SunDay }; int main(void) { //int day; //day定义成int类型不合适 enum WeekDay day = WednesDay; printf("%d ",day); return 0; }
枚举的优缺点:
代码更安全
书写麻烦
位运算符:
补码:
学习目标:
在C++中一个int 类型的变量所能存储的数字的范围是多少
最小负数的二进制代码是多少
最大正数的二进制代码是多少
已知一个整数的二进制代码求出原始的数字
数字超过最大正数会怎样
进制转换
字符串的处理
链表
算法:
通俗的定义:
解题的方法和步骤
狭义的定义:
对存储数据的操作
对不同的存储结构,要完成的某一功能所执行的操作是不一样的
广义的定义:
广义的算法也叫泛型
无论数据是如何存储的,对该数据的操作都是一样的
我们至少可以通过两种结构来存储数据
数组
优点:
存取速度快
缺点:
需要一个连续的很大的内存
插入和删除元素的效率很低
链表
专业术语:
头节点:头节点的数据类型和首节点的数据类型一模一样
头指针:存放头节点地址的指针变量
首节点:存放第一个有效数据的节点
尾节点:存放最后一个有效数据的节点
优点:
插入删除元素效率高
不需要一个连续的很大的内存
缺点:
查找某个位置的元素