null程序
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
技术程序设计技术C语言数据描述和C程序设计初步
结构化程序设计基础和C语言的控制结构
数组及其应用
函数与C程序结构
指针与函数
指针与数组
字符串及其应用
结构体类型和联合体类型
C语言的文件处理及其应用
位运算与枚举类型结构体类型和联合体类型 结构体类型和联合体类型 结构体数据类型的基本概念
结构体数组
结构体数据类型与指针的关系
结构体数据类型的简单应用——单链表
联合体数据类型的基本概念 结构体数据类型的基本概念 结构体数据类型的基本概念 由一些属于不同数据类型的数据组合而成的构造数据类型称为结构体类型。定义形式如下:
struct 标识符
{ 数据类型名 结构体成员1;
数据类型名 结构体成员i;
…
数据类型名 结构体成员n;
};
式中struct 标识符一起构成结构体数据类型的类型名;
数据类型名 结构体成员i;确定了结构体类型中的一个结构体成员,其定义形式如前面的变量定义;struct student
{ long id;
char name[20];
int age;
char sex;
char address[80];
long tel;
}; 结构体数据类型的基本概念 结构体数据类型的基本概念 定义结构体类型变量举例
先定义类型,然后定义变量
同时定义结构体类型和变量
只定义结构体类型变量结构体数据类型的基本概念 结构体数据类型的基本概念 结构体类型的嵌套定义
结构体类型可以嵌套定义,即定义的一个结构体类型的成员中可以有属于另外一个已经定义完成的结构体类型的变量。
struct date
{ int year;
int month;
int day;
};struct student
{ long number;
char name[20];
struct date birthday;
int age;
char address[80];
long tel;
};结构体数据类型的基本概念 结构体数据类型的基本概念 关键字typedef的简单应用
typedef关键字的主要作用
为已经存在的数据类型取一个新的名字(别名);
根据需要构造复杂的数据类型;
使用typedef 为已经存在的数据类型取别名
使用typedef可以为已经存在的数据类型取别名,定义别名后程序中既可以使用原类型名,也可以使用其别名。定义别名的一般形式为:
typedef 数据类型名 别名;
typedef int INTEGER;
(为系统整型int类型取别名INTEGER)
int j,k; 等价于 INTEGER j,k; typedef struct student
{ long number;
struct date birthday;
char name[20];
int age;
char sex;
char address[80];
long tel;
}STU;
struct student 等价于 STUstruct student
{ long number;
struct date birthday;
char name[20];
int age;
char sex;
char address[80];
long tel;
};
typedef struct student STU;
struct student 等价于 STU结构体数据类型的基本概念 结构体数据类型的基本概念 关键字typedef的简单应用
使用typedef构造复杂数据类型
在不同的应用环境中对复杂结构数据的要求是不同的,所以使用typedef关键字构造复杂结构数据没有统一的形式,在应用程序中应该根据需要构造合适形式的数据类型。
构造指定长度的字符串数据类型
typedef char String[100];
String是字符串数据类型的类型名,其每个变量都可以容纳最多99个有效字符。
String s1; 等价于 char s1[100];
例8-1 用typedef构造指定长度的字符串数据类型。结构体数据类型的基本概念 结构体数据类型的基本概念 关键字typedef的简单应用
使用typedef构造复杂数据类型
构造指定行列的二维数组类型
#define N 5
#define M 10
typedef int arr[N];
typedef arr Array[M];
Array是M行N列整型二维数组类型的类型名,其每个变量都是一个M行N列的整型二维数组。
Array a1; 等价于 int a1[M][N];
例8-2 用typedef构造指定行数和列数的二维数组类型 。结构体数据类型的基本概念 结构体数据类型的基本概念 关键字typedef的简单应用
使用typedef构造复杂数据类型
构造指针数据类型
typedef int *IP;
IP是整型指针类型的类型名,其每个变量都是指向整型数据的指针变量。
IP ptr; 等价于 int *ptr;
例8-3 用typedef构造指针数据类型。结构体数据类型的基本概念 结构体数据类型的基本概念 关键字typedef的简单应用
使用typedef构造复杂数据类型
构造指向函数的指针数据类型
typedef double (*FP)(double);
FP是指向函数指针类型的类型名,其每个变量都是一个指向拥有一个double类型形参、返回值类型为double的函数的指针变量。
FP ptr; 等价于 double (*ptr)(double x);
例8-4 用typedef构造指向函数的指针数据类型。
结构体数据类型的基本概念 结构体数据类型的基本概念 结构体变量的引用和输入输出
结构体变量的初始化
结构体变量初始化的形式类似于一维数组,其不同之处在于结构体变量的成员值根据其所属类型可以是不同类型的数据。初始化的一般形式为:
struct 标识符 变量名={结构体变量成员值列表};
例:struct student stu1={5001, “Liwei”,
19,’m’,“ 12 songlin”,65102621}; 结构体数据类型的基本概念 结构体数据类型的基本概念 结构体类型的定义和结构体变量的使用方法
结构体类型变量的引用
结构体变量一般也不能进行整体操作。只能通过对其中的每一个数据项的操作达到操作结构体变量的目的。对于结构体变量中每一个数据项(成员分量)的引用要使用点运算符以组合成结构体成员分量,其一般形式为:
结构体变量名.成员分量名
嵌套结构体类型变量的引用
对于嵌套的结构体类型的变量,访问其成员时应采用逐级访问的方法,直到得到所需访问的成员为止。其形式为:
结构体变量名.一级成员分量名.二级成员分量名… 结构体数据类型的基本概念 结构体数据类型的基本概念 结构体类型的定义和结构体变量的使用方法
结构体类型变量的输入输出
不允许把结构体变量作为整体进行输入或输出的操作,只能将结构体变量的成员作为输入输出的对象。
同类型结构体变量的赋值
当有两个同类型的结构体变量时,可以将一个结构体变量作为一个整体赋值给另外一个结构体变量。
例:struct student stu1 ={5001, “Liwei”,
19,’m’,“ 12 songlin”,65102621};
struct student stu2=stu1; 例8-5 结构体变量引用和输入输出示例。结构体数据类型的基本概念 结构体数据类型的基本概念 结构体变量作为函数参数
结构体类型变量可以作为函数的参数在函数之间进行传递。使用结构体类型变量作为函数参数时,数据的传递仍然是“值传递方式”;
实现方式:函数调用时系统为形参变量开辟一段内存单元(按照结构体变量所需要的存储单元数)以存放从实参传递过去的各结构体变量成员分量的值。
例8-6 结构体变量作为函数参数使用示例。
结构体数据类型的基本概念 结构体数据类型的基本概念 结构体作函数的返回值类型
返回结构体类型函数概念
结构体类型数据对象不但能够作为函数参数在函数之间传递,也可以作为函数的返回值。当函数的返回值类型是一个结构体类型时,该函数就称为返回结构体类型的函数。
函数定义的形式
struct 标识符 函数名(形式参数表及定义)
{ 函数的定义和声明部分;
函数的执行部分;
} 例8-7 返回结构体类型函数的使用示例。结构体类型和联合体类型 结构体类型和联合体类型 结构体数据类型的基本概念
结构体数组
结构体数据类型与指针的关系
结构体数据类型的简单应用——单链表
联合体数据类型的基本概念 结构体数组 结构体数组 结构体数组的定义和数组元素的引用
结构体数组概念
一个结构体变量可以存放一组数据以描述一个对象的相关信息,如果存在若干个同类型的对象则需要使用多个具有相同结构的结构体变量。可以将这些相同类型的结构体变量组成结构体数组。结构体数组中的每一个数组元素都是结构体变量,结构体数组特别适用于处理具有若干相同关系的数据组成的集合体。
结构体数组的定义
定义结构体数组的方式与定义结构体变量相同,也有3三种方法。如果以定义好结构体类型,则结构体数组定义的一般形式是:
struct 标识符 数组名[常量表达式]; 结构体数组 结构体数组 结构体数组的定义和数组元素的引用
结构体数组的存储形式
构体数组各元素在系统内存中连续存放,每一数组元素的成员分量也按类型定义中出现的顺序依次存放。
结构体数组的初始化
由于结构体数组元素(结构体变量)一般总是由若干不同类型的数据组成的,而且结构体数组又由若干个结构体变量组成,所以结构体数组的初始化形式总与较它高一维的普通变量数组的初始化形式类似。初始化的一般形式是:
struct 标识符 数组名[]={初始化数据列表};
例:设有结构体类型定义
sturct person
{ char name[20];
int count;
};
struct person stu[3]={“Zhang”,0,”Wang”,0,”Li”,0};
struct person stu[3]={{“Zhang”,0},{“Wang”,0},{“Li”,0}}; 结构体数组 结构体数组 结构体数组的定义和数组元素的引用
结构体数组元素的引用
结构体数组元素就相当于一个结构体变量,所以引用数组元素成员分量的方法与前面介绍的引用结构体变量成员分量的方法相同,其一般形式为:
数组名[下标].成员名
例8-8 结构体数组操作(数组元素引用、数组元素的输入输出)示例。
结构体数组 结构体数组 结构体数组作函数参数
结构体类型数组可以作为函数的参数在函数间进行传递。使用结构体类型数组作为函数参数时,实现的是“传地址值调用方式”。 同样实现的是实参数组将自己的全部或部分区域提供给形参数组共享的过程。 例8-9 结构体数组作函数参数示例。结构体类型和联合体类型 结构体类型和联合体类型 结构体数据类型的基本概念
结构体数组
结构体数据类型与指针的关系
结构体数据类型的简单应用——单链表
联合体数据类型的基本概念 结构体数据类型与指针的关系 结构体数据类型与指针的关系 结构体类型变量与指针的关系
概念
结构体类型变量的指针就是该结构体类型变量所占内存区域的起始地址,同样也可以定义一个指针类型的变量来存放这个地址,即指向这个结构体类型变量。
结构体指针定义形式
与定义其他类型的指针类似,也可以对同类型的变量、数组、指针变量等混合定义。指向结构体类型变量的指针变量定义形式为:
struct 标识符 *指针变量名;
结构体指针变量的赋值
使用取地址运算符将一个结构体变量的地址赋值给相应的指针变量。struct person
{ char name[20];
int count;
}stu, *p=&stu;
同样:对指针变量p取指针运算就是结构体变量stu结构体数据类型与指针的关系 结构体数据类型与指针的关系 结构体类型变量与指针的关系
通过指针变量访问结构体类型变量的成员分量
(*指针变量).成员名;
指针变量名->成员名; 结构体数据类型与指针的关系 结构体数据类型与指针的关系 结构体类型变量与指针的关系
结构体类型指针作为函数参数
使用结构体类型变量作为函数的参数时可以将整个结构体类型变量作为参数在函数之间进行传递,但这种方式实现的是“传值调用”,即要将全部成员值一个一个传递,既费时间又费空间,系统开销较大。
使用指向结构体类型变量的指针作为函数的参数以实现“传地址值调用”,这样可以不在函数之间传递大量的数据信息,从而可以大大提高应用程序的执行效率。
例8-10 输入若干个学生信息并输出,输入输出功能由函数实现。 结构体数据类型与指针的关系 结构体数据类型与指针的关系 结构体类型数组与指针的关系
struct A
{ char c;
int x;
};
struct A a[5],*p1;
p1=&a[2];
例8-11 用指向结构体数组元素的指针操作结构体数组元素示例。结构体数据类型与指针的关系 结构体数据类型与指针的关系 结构体类型数组与指针的关系
struct A
{ char c;
int x;
};
struct A a[5],*p2;
p2=a;
例8-12 输入若干个学生信息并输出。结构体类型和联合体类型 结构体类型和联合体类型 结构体数据类型的基本概念
结构体数组
结构体数据类型与指针的关系
结构体数据类型的简单应用——单链表
联合体数据类型的基本概念 结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表自引用结构和结点的定义
C语言中的自引用结构
在定义结构体构造数据类型的时候,结构体类型中的数据成员可以是该结构体类型自己的指针类对象(包括指针变量和指针数组)。这种在一个结构体类型定义中包含有该结构体类型指针类对象的结构体称为自引用结构。//正确的自引用结构
struct test
{ char ch;
struct test *next;
};//错误的自引用结构
struct test
{ char ch;
struct test next;
};结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表自引用结构和结点的定义
互相引用的自引用结构
在应用程序的设计中需要两个结构体对象相互引用,也可以使用一种自引用结构的变形,即在两个结构体类型的定义中分别包含指向对方的指针。
struct A
{ int x;
struct B *pb;
};
struct B
{ int y;
struct A *pa;
}; 例8-13 互相引用的自引用结构示例。结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表自引用结构和结点的定义
链表使用的数据元素——结点的定义
数据的逻辑结构
数据组织形式从逻辑上抽象地反映了数据元素之间的结构关系,则称这种数据之间的结构关系为数据的逻辑结构。数据的逻辑结构包含两个大类:线性结构和非线性结构,线性表是常见的一种数据逻辑结构。
数据的物理结构
用计算机对数据进行处理必须将数据存储到计算机中去,数据的逻辑结构在计算机存储设备中的映像(具体存储形式)称为数据的存储结构,亦称为数据的物理结构,在对线性表的处理中,其主要的存储结构有顺序存储结构和链式存储结构两种。
结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表自引用结构和结点的定义
链表使用的数据元素——结点的定义
线性链表使用一组任意的、可以不连续的存储单元存储线性表的数据元素,此时称线性表中的数据元素为结点。在线性链表的构造中,除第一个结点之外,其余每一个结点的存放位置由该结点的前趋在其指针域中指出。为了能够确定线性链表中的第一个结点的存放位置,使用一个指针指向链表的表头,这个指针称作“头指针”。线性链表的最后一个结点没有后继,为了表示这个概念,该结点的指针域赋值为空(NULL或∧)。链表与顺序表相比有许多优点:①链表结构可以根据处理数据的增减动态增长;②链表结构在进行数据元素的插入和删除操作的时候不需要移动数据元素。但与顺序表比较而言也有许多短处:①链表是一种顺序访问结构;②链表需要指针域用于结点之间的连接,因而链表的存储密度没有顺序表高。 结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表链表的基本操作
带头结点单链表的构造
单链表的构造方法有两种:
正向生成构造法
单链表的正向生成的步骤主要分为两步:首先创建单链表的头指针,然后将新结点依次链接到单链表的尾部。
反向生成构造法
单链表的反向生成的步骤主要分为两步:首先创建单链表的头指针,然后将新结点依次插入到单链表的头部。 反向生成法构造单链表算法:
NODE *create(int n) /* 构造具有n个结点的单链表 */
{ NODE *p,*h;
int i;
char inbuf[10];
h=(NODE *)malloc(sizeof(NODE)); /* 创建单链表的头结点 */
h->next=NULL;
for(i=n;i>0;i--)
{ p=(NODE *)malloc(sizeof(NODE)); /* 为每一个新结点分配存储 */
gets(p->name);
gets(inbuf);
p->score=atof(inbuf);
p->next=h->next; /* 将新建结点插入到单链表的头结点之后 */
h->next=p;
}
return h;
}结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表链表的基本操作
单链表的输出
所谓单链表的输出实质上就是对某一头指针指向的单链表进行遍历,也就是将单链表中的每一个数据元素结点从表头开始依次处理一遍。 带头结点单链表输出算法:
void printlist(NODE *h)
{ NODE *current=h;
while(current->next!=NULL)
{ current=current->next;
printf("%s\t%f\n",current->name,current->score);
}
}结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表链表的基本操作
单链表的插入运算 实现在单链表上插入一个结点的基本过程如下:
创建一个新结点;
按要求寻找插入点;
被插入结点的指针域指向插入点结点的后继结点;
插入点结点的指针域指向被插入的结点;带头结点的单链表中实现的插入结点算法:
void insertlist(NODE *h,char *s)
{ NODE *p,*old,*last;
char inbuf[20];
/* 创建新结点 */
p=(NODE *)malloc(sizeof(NODE));
printf("\tInput the data of the new node:\n");
gets(p->name);
gets(inbuf);
p->score=atof(inbuf);
结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表 last=h->next; /* 按某种方法寻找新结点的插入位置 */
while(strcmp(last->name,s)!=0&&last->next!=NULL)
{ old=last;
last=last->next;
}
if(last->next!=NULL) /* 找到插入位置,插入新结点 */
{ old->next=p;
p->next=last;
}
else /* 未找到插入位置,新结点添加到链表末尾 */
{ last->next=p;
p->next=NULL;
}
}结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表链表的基本操作
单链表的删除运算 实现在单链表中删除一个数据元素结点的基本过程如下:
查找被删除结点以及其前趋结点;
被删除结点的前趋结点指针域指向被删除结点的直接后继结点;
释放被删除结点; 带头结点的单链表中实现的删除结点算法:
void deletelist(NODE *h,char *s)
{ NODE *q=h,*p=h->next;
/* 定位被删除结点及其前趋*/
while(strcmp(p->name,s)!=0&&p->next!=NULL)
{ q=p;
p=p->next;
}
if(p->next!=NULL) /*找到被删除结点则将其从链表中删去*/
{ q->next=p->next;
free(p);
}
else /*找不到被删除结点则给出提示信息*/
{ printf("no this element!\n");
getch();
}
}结构体数据类型的简单应用——单链表结构体数据类型的简单应用——单链表链表的基本操作
例8-14 带头结点单链表基本操作示例。要求设计一个简单的菜单,根据对菜单项的选择分别实现带头结点单链表的构造操作、插入操作、删除操作和输出操作。
解题思想:分别设计出对带头结点单链表操作算法如下:
构造具有n个结点的单链表
NODE *create(int n);
在单链表中插入一个新的结点
void insertlist(NODE *h, char *s);
在单链表中删除一个指定结点
void deletelist(NODE *h, char *s);
输出单链表
void printlist(NODE *h); 结构体类型和联合体类型 结构体类型和联合体类型 结构体数据类型的基本概念
结构体数组
结构体数据类型与指针的关系
结构体数据类型的简单应用——单链表
联合体数据类型的基本概念 联合体数据类型的基本概念 联合体数据类型的基本概念 问题的提出及对策
问题的提出
在计算机应用的实践中,常常遇到数据对象的某一个区域值会随条件不同而为不同内容的情况。此时要求在程序设计中通过实现同一存储区域数据(类型)的可变性来增强数据项处理的灵活性。
解决方法
C程序设计语言通过支持定义联合体(共用体)类型数据来适应计算机程序设计中的上述要求。
联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型的定义和变量的引用方法
联合体类型的定义
联合体类型的定义确定了参与共用存储区域的成员项以及成员项具有的数据类型 。联合体类型定义的形式为:
union 标识符
{ 数据类型 成员项1;
数据类型 成员项2;
…
数据类型 成员项n;
}; 联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型的定义和变量的引用方法
联合体类型变量的定义
先定义联合体类型,然后定义联合体变量
union 标识符
{ 成员列表;};
union 标识符 变量列表;
定义联合体类型的同时定义联合体类型变量
union 标识符
{ 成员列表;}变量列表
不定义类型名直接定义联合体类型变量
union
{ 成员列表;}变量列表
union test
{ int a;
long b;
}key;
定义了一个联合体类型union test和一个该类型的联合体类型变量key,16位系统中该类型所占的存储单元长度为4个字节,由变量key的两个成员分量分时复用(共享)。
联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型的定义和变量的引用方法
联合体变量的引用
联合体变量不能直接用于操作处理,也只能通过操作它的成员达到操作它的目的。引用联合体类型变量的成员项的形式如下:
联合体类型变量名.成员名;
★特别提示:一个联合体类型变量不是同时存放多个成员的值,而只能存放一个成员项的值,这个值就是该联合体变量最后一次赋值后所具有的内容。
联合体类型指针变量
可以定义指向联合体变量的指针,进而通过指针使用联合体变量,定义形式和使用形式均与结构体类似。
联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型的定义和变量的引用方法
联合体类型变量和指针变量的使用示例
例8-15 联合体变量引用示例。
例8-16 编程是现简单的人事数据管理。在人事数据管理中,对“职级”数据项处理方式如下:如类别是工人则登记其“工资级别”;如类别是技术人员则登记其“职称”。联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型与结构体类型的区别
联合体类型和结构体类型无论在定义上还是在使用上都有许多相似的地方,但这两种数据类型是完全不同的数据构造形式,其使用的范畴也有区别。
结构体主要使用在需要将不同数据类型对象用类似数组方式集合起来表示复杂数据对象的场合;
而联合体主要用于不同数据对象在不同时段分时占用同一存储区域的应用场合。 联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型与结构体类型的区别
变量占据的存储区域长度不同
一个结构体类型变量中的所有成员分量同时存在,所以在使用该结构体类型变量时系统会为该变量的每一个成员分量同时分配存储空间。
一个联合体类型变量的所有成员分量不会同时存在,联合体类型变量在被使用时系统按照变量所有成员分量中需要存储区域最大的一个分配存储空间。
例8-17 结构体类型变量与联合体类型变量空间需要比较示例。联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型与结构体类型的区别
赋值后所呈现的状态不同
对于结构体类型变量,由于其每一个成员分量占用的是不同的存储空间,所以对其某一个成员分量的赋值与其它的成员分量没有任何关系。
对于联合体类型变量,所有成员分量是分时复用一段存储区域的关系,所以对其一个成员分量的赋值会影响到其它成员分量。
0x420x410x61/’a’0x62/’b’0x420x41 0x61 0x62例8-18 结构体类型变量与联合体类型变量赋值比较示例 联合体数据类型的基本概念 联合体数据类型的基本概念 联合体类型与结构体类型的区别
联合体可用于数据拆分的应用场合
联合体数据类型在C程序设计中常常用于将数据进行拆分的场合,这种应用问题往往需要将按某种形式(或数据类型)接收的数据拆分为另外形式或类型的数据。这种需要数据拆分的应用问题使用C语言中提供的联合体类型就非常适合,在C程序设计中将问题涉及到的两种数据类型组合在联合体类型中,然后使用该联合体的变量就可以处理这类问题。
例8-19 利用联合体数据类型实现文本的转换。