一、结构体
1、结构体变量的定义方式:
a.先定义好结构体类型,再定义该结构体类型变量。
struct student{ //定义类型:类型本身不占空间
int num;
int age;
float score;
};//注意后面有分号
struct student s1,s2;//定义变量:变量会在程序运行期间占内存b.在定义结构体类型的同时定义结构体变量。
struct student{
int num;
int age;
float score;
}student1,student2;
c.直接定义结构体变量:
struct{
int num;
int age;
float score;
}student1,student2;
这样定义结构体是没有结构体类型名的,
如需添加新的变量要求我们重新回到这里重新定义变量名。
PS:经常用的构造结构体的方法:
typedef struct student{
int name;
int age;
}stu_t;//把原来每次定义变量要输struct student换成每次输stu_t了。
stu_t s1,s2;//等价于struct student s1,s2;命名规则:常用下划线代表类型。
2、结构体变量成员:
引用结构体变量中的一个成员方式如下:
a.结构体变量名.成员名
b.指针变量名->成员名
struct student st,*pst;
st.num = 101;
pst-> = 95;
(*pst).age = 24;3、初始化(结构体变量赋值):
a.在对结构体变量进行赋值是,可以按每个成员在结构体中的顺序一一进行赋初值。
b.也可以只给前面的若干个成员赋值。
c.但不允许跳过前面的成员而给后面的成员赋值。
struct student s1 = {101,21,95};
struct student s2 = {102,22};
struct student s3 = {103, ,75};//错误4、结构体数组:
a.结构体数组的定义:
struct 结构体名 结构体数组名[元素个数];
struct student st[10];b.结构体数组成员的引用方式:
st[0].num = 101;
st[i].age = 24;5、结构体指针:
结构体指针是一个指针变量,用来指向一个结构体变量,例如:
struct student *st;思考题:思考下面两条语句的含义:
int a,age = 20;
a = st->age+1; //a = 21,age = 20
a = st->age++; //a = 21,age = 21
看这两条语句要注意变量本事有没有发生变化,比如第一条变量本身就没有发生变化。
st->age+1相当于(st->age)+1
st->age++相当于(st->age)++
6、课后练习程序:
程序1:编写一个程序,输入若干人员的姓名及电话号码,以字符'#'表示结束输入。然后输入姓名,查找该人的电话号码。
要求:使用结构体数组保存人员姓名和电话号码信息。
程序2:约瑟夫环问题:有n个小孩围成一圈,给他们从1开始编号,现在从第m个小孩开始报数,报到第s个时,该小孩出列,然后从下一个小孩开始报数,仍然是报到第s个时出列,如此重复下去,直到所有的小孩都出列,求小孩出列的顺序。
要求:要求使用结构体数组存储小孩的编号信息。
7、补充:
a.动态分配内存空间:malloc()和free()。
malloc函数原型:
typedef int size_t;
void *malloc(size_t size);
//(char*)malloc
//malloc(100,sizeof(int));使用malloc之前要判断:
if (malloc==NULL)
printf("error\n");内存碎片问题:内部碎片就是已经被分配出去(能明确指出属于哪个进程)却不能被利用的内存空间。外部碎片指的是还没有被分配出去(不属于任何进程),但由于太小了无法分配给申请内存空间的新进程的内存空闲区域。malloc申请内存是一次性申请所需的空间。
内存泄漏:用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元,直到程序结束(其实说白了就是该内存空间使用完毕之后未回收)。解决这个问题就是利用free()函数。
free((char*)cp);//用一个malloc()函数,就要用一次free()函数b.排序算法:
bubble_sort(冒泡排序):两个相邻的数进行比较,把较小的放在上面,较大的放在下面。这样一直比较,第一轮结束最大的在最下面。
select_sort(选择排序):用第一个数与后面每个数进行比较,每次比较选择最小的放在第一位,这样第一轮结束可以得出第一位是最小的。
二、链表
链表是一个数据结构。结构包括数据,操作包括增删改查。(建立链表、显示链表、查找节点、插入节点、删除节点、释放链表)
显示链表数据等于遍历链表。
1、链表定义:画个图吧
typedef struct node{
data;
struct node *next;//单向链表,双向链表再设计一个指向前面的指针
}node_t;2、动态链表:每一个结点都利用malloc()函数实现。第一个结点的头指针head,利用头指针来向后查找。
*head = corpointer;//利用head指针指向当前结点来访问每个结点*tail 尾指针,从尾指针向前遍历每个结点。//前提双向链表
3、创建结点:插入到最后尾插,插入到最前头插。
a.创建新结点malloc(sizeof(node_t));
结点地址->指针变量
数据域:一般是数据结构中的东西,简而言之就是存放数据的区域。
指针域:一般是在链表中的结点,数据域存放数据,指针域存放指向下一个结点的指针,以实现链表彻底线型结构。
b.找到链表尾部:只有头指针的从头开始查找,有尾指针的直接从尾部插入。
c.头部插入:(注意判断)
node_t *head;
head=(node_t*)malloc(sizeof(node));
if(NULL==head)
printf("error\n");
尾插代码:
tail->next = p;
p->next = NULL;//尾插
三、共同体 1、共用体变量定义:
a.在C语言中,可以定义不同类型的数据使用公用的存储区域,这种形式的数据构造类型称为共用体。
b.共用体类型和结构体类型在定义、说明和引用的形式很相似,但它们在存储空间的占用和分配上有本质的区别。
2、共用体类型的定义的一般形式如下:
union 共用体类型名
{
数据类型 成员名1;
数据类型 成员名2;
......
数据类型 成员名3;
}3、共用体变量:
a.共用体变量的定义: union 共用体类型名 共用体变量表;
b.共用体变量的引用:
共用体变量名.成员名
共用体指针变量名->成员名
(*共用体指针变量名).成员名
4、共用体变量特点:共用体变量中的所有成员共享一段公共存储区,所以共用体变量所占内存字节数与其成员中占字节数最多的那个成员相等。
union data{
int i;
char ch;
float f;
}//占用四个字节a.每一瞬时,共用体变量
只有一个成员起作用,其它的成员不起作用。
b.共用体变量中起作用的成员是最后一次存放的成员。
c.不能直接对共用体变量赋值,也不能直接通过引用共用体变量名来得到一个值。
union data a;
a = 1;
int m;
a.i = 1;
m = a;5、编程:
程序3:编写一个程序,输入一个长整数,然后分别取出该数各字节的值。提示:定义如下共用体:
union data{
unsigned char s[4];
long n;
};程序4:编写一个程序,读入N(N≤50)个职工数据,每个职工的数据包括工号、姓名、类型(t/g)。类型若为干部(g),还要输入级别;若为教师(t),还要输入系别、职称。最后输出这些数据。
四、枚举类型
1、枚举:枚举是一个命名为整形常量的集合。
2、枚举的定义形式如下:
enum 枚举名{枚举元素表} 枚举变量表;其中:其中,
枚举元素表由一系列符号组成,也称为枚举常量表,
每个符号都表示一个整数值。
enum week_day{
Mon,Tue, Wed,Thu,Fri,Sat,Sun}week;
3、枚举元素是按常量处理的,如果
没有进行初始化,第一个枚举元素的值是0,第二个枚举元素的值是1,依此类推
week = Fri;
printf("%d",week);//输出为4
假如把Mom赋值10,则后面为11、12......。若把Wed赋值为10,则Mon和Tue任然为0和1,但是Wed后面的变成了11、12...。4、对应的枚举变量只能取“枚举元素表”中的某个元素,而不能取其他值,如果不能把整数直接赋给枚举变量,例如:
week = Wed;//正确
week = 2;//错误
5、若想将整数值赋给枚举变量,需要强制类型转换,例如:
week = (enum week_day)2;
6、编程:
程序5:要求从键盘输入一个整数,显示与该整数对应的日期(星期一~星期天分别为1~7)
要求使用枚举体变量i接受键盘的输入
五、用户自定义类型
1、C语言允许用typedef说明一种新的类型名。
2、定义形式如下:
typedef 类型名1 类型名2;
其中“类型名1”是系统提供的标准类型名或已经定义过的其它类型名,“类型名2”就是用户定义的类型名
3、
typedef int INTEGER;
typedef struct
{int no;
char *name;
} PERSON;
typedef char NAME[10];
typedef char * POINT;4、
#include
typedef char NAME[10];
main(){
NAME a;
int i;
for(i=0;i<10;i++)
{
a[i]=i;
printf("%d\n",a[i]);
}
}5、
#include
#include
typedef char * POINT;
main(){
POINT a = (char *)malloc(10*sizeof(int));
int i;
for(i=0;i<10;i++)
{
a[i]=i;
printf("%d\n",a[i]);
}
}6、注意事项:
a.使用typedef只能定义各种用户定义的类型名,不能用于定义变量。
b.用户定义类型相当于原类型的别名,例如:
typedef char * NAME;
NAME p;//等价于char *p;c.
typedef定义类型名有利于程序的移植。
7、typedef与#define的区别:
typedef (int*) pINT1;//是一条语句,有分号
pINT1 a,b;//相当于int *a,*b;
#define pINT2 int*
pINT2 a,b;//相当于int *a,b;
typedef并不只做简单的字符串替换
8、编程:
程序6:编写一个程序,从键盘输入一行字符,调用一个函数建立反序的单链表,然后输出整个链表
链表定义如下:
typedef struct node
{int data;
struct node *next;
} NODE;