实验报告
一、 实验名称:商品信息管理系统
二、 实验学时:4 学时
三、 实验目的:
1. 掌握单链表的定义和使用方法
2. 掌握链表的建立方法
3. 掌握链表中节点的查找与删除
4. 掌握输出链表节点的方法
5. 掌握链表节点排序的一种方法
6. 掌握 C 语言创建菜单的方法
7. 掌握结构体的定义和使用方法
8. 掌握字符串的定义和使用方法
四、 实验原理:
1. 结构体:结构是可能具有不同类型的值(成员)的集合,结构的元素(在 C
语言中的说法是结构的成员)可能具有不同的类型。而且每个结构成员都
有名字,所以为了选择特定的结构成员需要指明结构成员的名字而不是
它的位置。
2. 结构变量的声明:当需要存储相关数据项的集合时,结构是一种呵护逻辑
的选择。例如假设需要记录存储在仓库中的零件。用才存储每种零件的
信息可能包括零件的编号(证书)、零件的名称(字符串)以及现在有零件的
数量。为了产生一个可以存储全部三种数据项的变量,可以使用类似下
面这样的声明:
结构 part1 和 part2 中的成员 number 和成员 name 不会与结构 employee1
和 employee2 中的成员 number 和成员 name 冲突。
struct{
int number;
char name[NAME_LEN+1];
int on_hand;
} part1,part2;
每个结构变量都有三个成员:number(零件的编号)、name(零件的名称) 和
on_hand(现有数量)。注意这里的声明格式和 C 语言中其他变量的声明格
式一样。struct{...}指明了类型。而 part1 和 part2 则是具有这种类型的变
量。结构的成员在内存中是按照声明的顺序存储的。
3. 每个结构代表一种新的作用域。任何声明中此作用域内的名字都不会和
程序中的其他名字冲突。(用 C 语言的术语可以表述为: 每个结构都为
它的成员设置了独立的名字空间(name space))例如,下来声明可以
出现在同一程序中:
struct{
int number;
char name[NAME_LEN+1];
int on_hand;
}part1,part2;
struct{
int number;
char name[NAME_LEN+1];
char sex;
}employee1, employee2;
4. 结构变量的初始化:和数组一样,结构变量也可以在声明的同时进行初始
化。为了对结构进行初始化,要把待存储到结构中的值的列表准备好并
用花括号把它括起来:
struct{
int number;
char name[NAME_LEN+1];
int on_hand;
}part1 = {528,”Disk drive”,10}, part2 = {914,”Printer cable”,5};
初始化式中的值必须按照结构成员的顺序进行显示。结构初始化式遵循
的原则类似于数组初始化式的原则。用于结构初始化式的表达式必须是
常量。例如,不能用变量来初始化结构 part1 的成员 on_hand。
5. 对结构的操作:既然最常见的数组操作是取下标,那么结构最常用的操作
是选择成员也就无需惊讶了。但是结构成员是通过名字而不是通过位置
访问的。为了访问结构内的成员,首先写出结构的名字,然后写一个句
点,再写出成员的名字。例如,下列语句显示结构 part1 的成员的值:
printf(“Part number:%d\n”, part1.number);
printf(“Part name:%s\n”,part1.name);
printf(“Quantity on hand:%d\n”,part1.on_hand);
结构的成员是左值,所以它们可以出现在复制运算的左侧,也可以作为
自增或自减表达式的操作数:
Part1.number = 258;
Part1.on_hand++;
用于访问结构成员的句点实际上就是一个 C 语言的运算符,句点运算符
的优先级几乎高于所有其他运算符。
结构的另一种主要操作是赋值运算:
part2 = part1;
这一句的效果是把 part1.number 复制到 part2.number,把 part1.name
复制到 part2.name,依次类推。
6. 结构标记:结构标记是用于标识某种特定结构的名字。下面的例子声明了
名为 part 的结构标记:
struct part{
int number;
char name[NAME_LEN+1];
int on_hand;
};
一旦创建了标记 part,就可以用它来声明变量了:
struct part part1,part2;
但是,不能通过漏掉单词 struct 来缩写这个声明:
part part1,part2; //错误声明
因为 part 不是类型名。如果没有单词 struct 的话,它没有任何意义。
7. 结构类型的定义:除了声明结构标记,还可以用 typedef 来定义真是的类
型名。例如,可以按照如下方式定义名为 Part 的类型:
typedef struct {
int number;
char name[NAME_LEN+1];
int on_hand;
}Part;
注意,类型 Part 的名字必须出现在定义的末尾,而不是在单词 struct
的后边。可以像内置类型那样使用 Part。
例如,可以用它声明变量:
Part part1,part2;
8. 链表存储结构:在链式存储结构中,存储数据结构的存储空间可以不连
续,各数据结点的存储顺序与数据元素之间的逻辑关系可以不一致,而
数据元素之间的逻辑关系是由指针域来确定的。链式存储方式即可以用
于表示线性结构,也可用于表示非线性结构。一般来说,在线性表的链
式存储结构中,各数据结点的存储符号是不连续的,并且各结点在存储
空间中的位置关系与逻辑关系也不一致。对于线性链表,可以从头指针
开始,沿各结点的指针扫描到链表中的所有结点。
9. 链表节点的类型:链表节点的类型应该包括存储元素的数据域,一般用
data 表示,它的类型可以是前期定义的元素结构体,以及包括存储后续
节点位置的指针域,此处用 next 表示。最后一个结点的 next 指针域为
空。例如下面定义一个商品的链表节点:
typedef struct node
{
GoodInfo data;
struct node *next;
}GoodList;
10. 单链表的头结点:线性表的链接存储中,为了方便在表头插入和删除结
点的操作,经常在表头结点(存储第一个元素的结点)的前面增加一个
结点,称之为头结点或表头附加结点。这样原来的表头指针由指向第一
个元素的结点改为指向头结点,头结点的数据域为空,头结点的指针域
指向第一个元素的结点。
11. 链表的基本操作函数:
a) InitList(&L):链表初始化,构造一个空的链表 L,主要工作为 L 头结
点分配空间。例如:
GoodList* pGoodList = (GoodList*)malloc(sizeof(GoodList));
b) DestroyList(&L):销毁链表 L,需要链表 L 存在的情况下执行。主要
工作为释放 L 的每个节点的空间。
c) ListEmpty(L):判断 L 是否是空表,返回 TRUE 或者 FALSE
d) ListLength(L):在 L 存在的情况下,计算 L 的结点数。
e) GetElem(L,i):在 L 存在的情况下,且 i 值在链表结点数范围内。返回
链表第 i 个元素的值。
f) ClearList(&L):在链表 L 存在的情况下将 L 重置为空表。
g) ListInsert(&L,i,e):在 L 存在的情况下,且 1<=i<= ListLength(L),在 L
第 i 个元素之前插入新的元素 e.
h) ListDelete(&L,i):在 L 存在的情况下,且 1<=i<= ListLength(L),删除
L 的第 i 个元素
12. 系统选择界面:可以通过一个 while 条件为 1 的循环来完成程序功能的
循环调用,直至输入退出系统的命令。例如:
while(1)
{
switch(choice){
case 1:Fucntion1;
break; ...
} }