链表是怎么发展来的
线性表:是n个具有相同特性的数据元素的有限序列。
链表:具有线性存储结构的线性表。
为什么需要使用链表?(链表是如何被设计出来的)
程序开发最重要的部分是如何在项目程序中找到一种合适的、好的数据表示方法,这样可以让程序设计起来更容易,数据处理算法更为简单。
C语言的内置数据类型有:简单变量、数组、指针、结构体、联合、枚举等。
找到正确的数据表示方法不仅是选择一种数据类型,而是要考虑进行哪些数据操作,要确定如何存储数据,如何访问数据,如何为数据类型定义有效的操作(增删查改)。
举例:创建通讯录
思考 应该使用什么数据形式存储信息?
由于通讯录的每个人的个人信息有多种,所以使用结构体来表示比较合适。
如何表示多个人?用结构体数组、动态数组还是其他形式。
每个人是否要按照首字母顺序排列?是否要用名字来查找通讯录里的人?
程序设计的需求(行为或操作将影响如何存储信息)
程序举例:
编写一个程序,输入某组织人员的名字和年龄(有多种信息),先从简单的开始。
软件结构-流程图如下
程序知识点预先讲解,有关逻辑方面与边界条件,参照软件流程图。
知识点1:
- fgets函数:
第一个参数,待读取数据的地址;
第二个参数,指明读入字符的最大数量
第三个参数,指明要读入的文件,如果是使用键盘输入,该参数要设置为stdin(标准输入),并在源文件包含stdio.h头文件;
返回值,是一个指向char类型的指针,正常情况下,该返回值返回的地址与第一个参数的地址相同,如果读到文件末尾,则返回NULL;
注意:fgets会把“\n”放在字符串末尾,这与其他的字符处理函数不同,因此需要额外的处理一下“\n”。
知识点2:
- strchr函数,如果未找到指定字符返回NULL。
#include <stdio.h>
#include <string.h>
#define PNUM 100 //总人数
#define NAME_SIZE 20//人名字符大小
typedef struct peoplecard
{
char name[NAME_SIZE];
int age;
}
char* manage_gets(char str[],int len_limt);
int main(void)
{
peoplecard peol[PNUM];//定义组织人员结构体数组
int i,j;
puts(“Enter first peol name”);//输入第一个人员的名字
while((i < PNUM)&&( manage_gets(peol[i].name, NAME_SIZE)!=NULL) &&( peol[i].name[0]!=’\0’))
{
puts(“Enter your age <0-200>:”);
scanf(“%d”,& peol[i++].age);
while(getchar()!=’\n’)
{
continue;
}
puts(“Enter next people name(empty line to stop):”);
}
if(i==0)
{
puts(“No data enter!”);
}
else
{
printf(“ Here is the people list:\n”);
for(j=0;j<i;j++)//是小于i而不是i+1,因为在前面i会多加一次。
{
printf(“people :%s, age:%d\n”, peol[j].name, peol[j].age);
}
printf(“end!\n”);
}
return 0;
}
char* manage_gets(char str[],int len_limt)
{
char* ret_val;
char* find;
ret_val = fgets(str,len_limt,stdin);
if(ret_val)
{
find = strchr(str,’\n’);
if(find)
{
*find = ‘\0’;
}
else
{
while(getchar()!=’\n’)
{
continue;
}
}
}
return ret_val;
}
总结:
该程序存在的缺点:定义的结构体数组的大小为固定的,如果人员数量少于其大小,存在空间浪费的问题,如果人员数量多于其大小,出现信息无法全部录入的问题。
用while做条件判断可能存在的问题:无法判断程序是因何种原因无法正常执行,可以将条件1数量判断放到while循环中。