Bootstrap

(带头节点的链表) 宿舍管理系统

前言:好多电子科技类大学的好多专业在大一或是大二实习的时候,会要求学生做类似于:图书馆管理系统,宿舍管理系统,学生管理系统和公司管理系统等等的系统。
其实,这些系统究其本质都是要求最少做一个能够对信息进行:增,删,改,查的操作的系统,那么,我就用这篇博客来编写一个宿舍管理系统来介绍链表的使用方法吧。

在这里,我要先介绍一下链表的概念:

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
那么,用图像表示为:
这里是引用
这里的h为头节点,其他节点的左部分为数据域,右部分为指针域,最后一个节点的指针域指向NULL

第一步,我们要思考将来要录入什么信息,而对于宿舍管理系统,则至少需要录入的信息是:
学生姓名,学生所住的楼号,层数,房间号
那么,我们就来定义一个结构体包含这几项信息:

typedef struct POINT {
	char name[20];       //这里定义长度是20,是因为一个汉字占用两个char类型的空间,所以,假设姓名在10 位以内
	int num;
	int ceng;
	int fang;
	struct POINT *next;  //这里的指针域,必须赋值,而且最后一个节点,要赋值为NULL 
}POINT;

第二步,因为在处理信息时,可能会出现处理失败的结果,所以,我们创建一个类型去识别是否成功(即,编写“lhc.h”):
(注意:.h文件中只能存放:函数声明,宏和用户自定义类型)

#ifndef _LHC_H_                         //防止多次定义造成错误
#define _LHC_H_

typedef unsigned char boolean          //模仿JAVA中的boolean ,定义一个新的数据类型
#define TRUE 1
#define FALSE 0

#define KEEP_ON 	1
#define EXIT    	0

typedef struct POINT {
	int num;
	int ceng;
	int fang;
	char name[20];
	struct POINT *next;
}POINT;

boolean defend();
void menu();
void initList(POINT *linkOne);
boolean enteringPoints(POINT *head);
void insertPoint(POINT *head);
POINT *searchPreNode(POINT head, POINT one);
boolean removePoint(POINT *head);
boolean alterPoint(POINT *head);
void showOnePoint(POINT point);
void showPointList(POINT head);
void destoryPointLink(POINT *head);
void sortByRow(POINT head);
int function(POINT *linkOne);

#endif

第三步,开始编写功能函数
1.因为要对信息进行处理的前提是有信息能够进行操作,所以,编写录入信息函数

boolean enteringPoints(POINT *head) {	 //返回值为boolean 类型,是因为这里的参数是 存储 我们要录入信息的链表的首地址
	int pnum;
	int pceng;
	int pfang;
	char pname[20];  //前面这四个变量的定义,是为了将来用户输入以及给链表数据域赋值用的
	
	POINT *p;       //这个变量的功能是存储一个要变动变量未变动之前的数据的地址
	POINT *tail;

	if(NULL == head || head->next != NULL) {
			return FALSE;
	}
		
	printf("请输入楼号,层数,房间,姓名:");
	scanf("%d%d%d", &pnum, &pceng, &pfang);
	gets(pname);
		
	while(pnum && pceng && pfang) {
		p=(POINT *)calloc(sizeof(POINT), 1);
		p->num=pnum;
		p->ceng=pceng;
		p->fang=pfang;
		strcpy(p->name, pname);
			
		if(NULL == head->next) {
			head->next=p;
		} else {
			tail->next=p;
		}
		tail=p;
		printf("请输入楼号,层数,房间,姓名:");
		scanf("%d%d%d", &pnum, &pceng, &pfang);
		gets(pname);
	}
	return TRUE;
}

2.编写增添数据的函数(即插入数据函数)

在这里,因为增添数据可能是左插入,也可能是右插入,那么,在这里,我就用最常用的左插入来编写插入数据函数:

void insertPoint(POINT *head) {
	int newNum;
	int newCeng;
	int newFang;
	char newName[20];  //前面这四个变量,是为用户输入新居民信息用的
	int oldNum;
	int oldCeng;
	int oldFang;
	char oldName[20];  //这四个变量,是旧居民(即新居民后面的居民)的信息
	POINT *p;
	POINT old;
	POINT *pre;


	printf("请输入新用户信息:");
	scanf("%d%d%d", &newNum, &newCeng, &newFang);
	gets(newName);
	p = (POINT *) calloc(sizeof(POINT), 1);
	p->num = newNum;
	p->ceng = newCeng;
	p->fang = newFang、;
	p->next = NULL;

	printf("请输入指定用户信息(楼号,层数,房间号、姓名)(实现左插入;若指定点不存在,则,实现尾随追加):");
	scanf("%d%d%d", &oldNum, &oldCeng, &oldFang);
	gets(oldName);
	old.num = oldNum;
	old.ceng = oldCeng;
	old.fang = oldFang;

	pre = searchPreNode(head, old);

	if (NULL == pre) {	//判断是否为空链表
		pre = head;
	}
	p->next = pre->next;
	pre->next = p;
}

以下是该函数原理的示意图:
在这里插入图片描述
3.增删改查函数差不多都会用到查找函数,那么,我们就来编写查找函数

POINT *searchPreNode(const POINT *head, POINT one) {
	POINT *p;
	POINT *q = NULL;

	for (p = head->next; p && (p->num != one.num || p->ceng != one.ceng || p->fang != one.fang); p = p->next) {
		q = p;
	}

	return q;    //q为要查找的节点的前驱结点的首地址
}

4.有增添就要想到删除,所以,编写删除函数

boolean removePoint(POINT *head) {       //因为用户可能输入错误信息,导致删除操作失败,所以,返回值为boolean 类型
	int num;
	int ceng;
	int fang;
	char name[20];
	POINT *pre;
	POINT point;
	POINT *p;


	printf("请输入要删除的用户信息(按照楼号,层数,房间号):");
	scanf("%d%d%d", &num, &ceng, &fang);
	gets(name);
	point.num = num;
	point.ceng = ceng;
	point.fang =fang;
	strcpy(point.name,name);
	pre = searchPreNode(head, point);
	if (NULL == pre) {
		pre = head;
	} else if (NULL == pre->next) {	//若不是链表内的值,则无需进行删除,直接返回即可
		return FALSE;
	}
	p = pre->next;
	pre->next = p->next;
	free(p);

	return TRUE;
}

在这里插入图片描述
5.编写修改用户信息的函数

boolean alterPoint(POINT *head) {       //因为用户可能输入错误信息,导致删除操作失败,所以,返回值为boolean 类型
	int oldnum;
	int oldceng;
	int oldfang;
	char oldname[20];
	int newnum;
	int newceng;
	int newfang;
	char newname[20];
	
	POINT newPoint;
	POINT target;
	POINT *pre;
	
	if(!head) {
		return FALSE;
	}
	
	printf("请输入要修改的用户的信息:");
	scanf("%d%d%d", &oldnum, &oldceng, &oldfang); 
	gets(oldname);
	target.num=oldnum;
	target.ceng=oldceng;
	target.fang=oldfang;
	strcpy(target.name,  oldname);
	
	pre = searchPreNode(head, target);
	if(!pre || NULL !=pre->next ) {
		printf("请输入新的用户信息:");
		scanf("%d%d%d", &newnum, &newceng, &newfang); 
		gets(newname);
		pre->next->num=newnum;
		pre->next->ceng=newceng;
		pre->next->fang=newfang;
		strcpy(pre->next->name, newname);
		
		return TRUE;
	} 
	return FALSE;
}

6.编写显示函数
因为一个一个显示都要进行一个重复的步骤,就是显示一个居民的信息,
那么,就先编写显示一个居民的信息的函数

void showOnePoint(const POINT *point) {
	printf("                                %-d        %-d        %-d        %s         \n",point.num,point.ceng,point.fang,point.name);
}

在此基础上,再来编写显示全部居民信息的函数:

void showPointList(const POINT *head) {
	POINT *p;
	printf("\n                           ---------------------------------------------");
	printf("\n                               楼号     层数     房间号     户主姓名\n");
	for (p = head->next; p; p = p->next) {
		showOnePoint(p);
	}
	printf("                           ---------------------------------------------");
	printf("\n");
}

7.因为用户可能会有销毁当前信息表的需求,所以这一步编写销毁当前信息表的函数

void destoryPointLink(POINT *head) {
	POINT *p;

	while (head && head->next) {
		p = head->next;
		head->next = p->next;
		free(p);
	}

	head->next = NULL;
}

8.可能用户会有将信息排序的需求,所以,这里来编写排序函数

void sortByRow(POINT *head) {
	POINT *pre;
	POINT *next;
	POINT *nextTemp;
	POINT temp;

	for (pre = head->next; pre; pre = pre->next) {	//我们在这里用的是冒泡排序法
		for (next = pre->next; next; next = next->next) {
			if ((pre->num >= next->num) && (pre->ceng >= next->ceng) && (pre->fang >= next->fang)) {  
				temp = *pre;       //这里是按照楼号->层数->房间号顺序,从大到小排序的
				*pre = *next;
				*next = temp;

				nextTemp = pre->next;
				pre->next = next->next;
				next->next = nextTemp;
			}
		}
	}
}

第三步谋划主函数
为了在没有多少技术的基础上显示自己的逼格,这里就可以编写一个简易的安全锁函数

boolean defend() {
	int ok=	0;
	char code[20];               
	int count=0;
	
	printf("                                    安全监测系统\n");
 	printf("            请输入8位密码(初始密码为12345678;两次错误输入后,程序结束):\n");
	while(!ok && count < 2) {
		gets(code);
		ok=(0 == strcmp(code,"12345678"));
		if (!ok) {
			printf("\n密码错误,");
			++count;
		} else {
			ok = 1;
		}
		if(!ok&&count<2) {
		printf("请再次输入: ");
		}
	}
	if (ok) {
		printf("\n\1小区管理系统欢迎您\1\n");
		return TRUE;
	} else {
		printf("很遗憾,程序结束\n");
		return FALSE;
	} 
}

因为之前做了很多功能函数,在主函数中就可以让用户选择要使用的功能函数,完成对于信息的处理,而且,在完成信息的处理操作后,还需要询问用户是否结束运行,如果否,则继续执行之后的指令。
而有了这个想法,我们不妨编写一个菜单函数:

void menu() {
	printf("\n                                              小区户主信息管理系统\n ");
	printf("            ****************************************************************************************************************\n");
	printf("            |--------------------------------------------------------------------------------------------------------------|\n");
	printf("            |      1             2             3             4              5                6       			7  		   |\n");
	printf("            |--------------------------------------------------------------------------------------------------------------|\n");
	printf("            |    终止程序    用户信息插入   用户信息排序   用户信息显示   用户信息删除       用户信息表销毁       用户信息修改    |\n");
	printf("            |--------------------------------------------------------------------------------------------------------------|\n");
	printf("            ****************************************************************************************************************\n");
	printf("请输入指令:(输入其他数字表示结束程序)\n");
}

一切就绪,那么,我们现在来编写主函数吧:

int main() {
	POINT linkOne = {0};
	boolean safe;
	int flag = 1;
	
	printf("制作人: xx专业    xxx\n");
	safe = defend();
	if(safe == FALSE) {
		return 0;
	}

	initList(&linkOne);

	while(flag) {
		flag = function(&linkOne);
	}
	
	return 0;
}

那么,现在来总结一下 manageSystem.c 的内容:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

#include "lhc.h"

int function(POINT *linkOne) {
	int order;
	int ok;

	scanf("%d",&order);
	switch(order)  {
		case 1: 
			insertPoint(linkOne);
			showPointList(*linkOne);
			break; 
					
		case 2: 
			sortByRow(*linkOne);
			showPointList(*linkOne);
			break; 
					
		case 3: 
			showPointList(*linkOne);
			break; 
					
		case 4: 
			if(TRUE == removePoint(linkOne)) {
				printf("删除结果如下:\n");
				showPointList(*linkOne);
			} else {
				printf("删除失败!\n");
			}
			break; 
					
		case 5: 
			alterPoint(linkOne);
			printf("修改结果如下:\n");
			showPointList(*linkOne);
			break; 
			
		case 6:
			destoryPointLink(linkOne);
			printf("用户信息表已被销毁!!!\n");
			printf("输入1:重新录入信息\n输入其他:终止程序!\n");
			scanf("%d", &ok);
			if(1 != ok) {
				printf("即将终止程序...\n");
				return EXIT;
			}
			initList(linkOne);
			break; 
						
		default : 
			destoryPointLink(linkOne);
			return EXIT;
	}
	printf("\n输入任意继续程序...\n");
	getchar();
	getchar();
	menu();
	return KEEP_ON;
}

void insertPoint(POINT *head) {
	int newNum;
	int newCeng;
	int newFang;
	char newName[20]; 
	int oldNum;
	int oldCeng;
	int oldFang;
	char oldName[20];  
	POINT *p;
	POINT old;
	POINT *pre;


	printf("请输入新用户信息:");
	scanf("%d%d%d", &newNum, &newCeng, &newFang);
	gets(newName);
	p = (POINT *) calloc(sizeof(POINT), 1);
	strcpy(p->name, newName);
	p->num = newNum;
	p->ceng = newCeng;
	p->fang = newFang;
	p->next = NULL;

	printf("请输入指定用户信息:楼号、层数、房间号(实现左插入;若指定用户不存在,则,实现尾随追加):");
	scanf("%d%d%d", &oldNum, &oldCeng, &oldFang);
	old.num = oldNum;
	old.ceng = oldCeng;
	old.fang = oldFang;

	pre = searchPreNode(*head, old);

	if (NULL == pre) {

		pre = head;
	}
	p->next = pre->next;
	pre->next = p;
}

POINT *searchPreNode(POINT head, POINT one) {    
	POINT *p;
	POINT *q = NULL;

	for (p = head.next; p && (p->num != one.num || p->ceng != one.ceng || p->fang != one.fang); p = p->next) {
		q = p;
	}

	return q;    
}

boolean removePoint(POINT *head) {      
	int num;
	int ceng;
	int fang;
	char name[20];
	POINT *pre;
	POINT point;
	POINT *p;


	printf("请输入要删除的用户信息(按照楼号,层数,房间号):");
	scanf("%d%d%d", &num, &ceng, &fang);
	gets(name);
	point.num = num;
	point.ceng = ceng;
	point.fang =fang;
	strcpy(point.name,name);
	pre = searchPreNode(*head, point);
	if (NULL == pre) {
		pre = head;
	} else if (NULL == pre->next) {
		return FALSE;
	}
	p = pre->next;
	pre->next = p->next;
	free(p);

	return TRUE;
}

boolean alterPoint(POINT *head) {     
	int oldnum;
	int oldceng;
	int oldfang;
	char oldname[20];
	int newnum;
	int newceng;
	int newfang;
	char newname[20];
	
	POINT newPoint;
	POINT target;
	POINT *pre;
	
	if(!head) {
		return FALSE;
	}
	
	printf("请输入要修改的用户的信息(按照楼号,层数,房间号,用户名):");
	scanf("%d%d%d", &oldnum, &oldceng, &oldfang); 
	gets(oldname);
	target.num=oldnum;
	target.ceng=oldceng;
	target.fang=oldfang;
	strcpy(target.name,  oldname);
	
	pre = searchPreNode(*head, target);
	if(!pre || NULL !=pre->next ) {
		printf("请输入新的用户信息(按照楼号,层数,房间号,用户名):");
		scanf("%d%d%d", &newnum, &newceng, &newfang); 
		gets(newname);
		pre->next->num=newnum;
		pre->next->ceng=newceng;
		pre->next->fang=newfang;
		strcpy(pre->next->name, newname);
		
		return TRUE;
	} 
	return FALSE;
}

void showOnePoint(POINT point) {
	printf("                                %-d        %-d        %-d        %s         \n",point.num,point.ceng,point.fang,point.name);
}

void showPointList(POINT head) {
	POINT *p;
	printf("\n                           ---------------------------------------------");
	printf("\n                               楼号     层数     房间号     户主姓名\n");
	for (p = head.next; p; p = p->next) {
		showOnePoint(*p);
	}
	printf("                           ---------------------------------------------");
	printf("\n");
}

void destoryPointLink(POINT *head) {
	POINT *p;

	while (head && head->next) {
		p = head->next;
		head->next = p->next;
		free(p);
	}

	head->next = NULL;
}

void sortByRow(POINT head) {
	POINT *pre;
	POINT *next;
	POINT *nextTemp;
	POINT temp;

	for (pre = head.next; pre; pre = pre->next) {
		for (next = pre->next; next; next = next->next) {
			if ((pre->num >= next->num) && (pre->ceng >= next->ceng) && (pre->fang >= next->fang)) {
				temp = *pre;
				*pre = *next;
				*next = temp;

				nextTemp = pre->next;
				pre->next = next->next;
				next->next = nextTemp;
			}
		}
	}
}

boolean enteringPoints(POINT *head) {	
	int pnum;
	int pceng;
	int pfang;
	char pname[20];  //前面这四个变量的定义,是为了将来用户输入以及给链表数据域赋值用的
	
	POINT *p;       //这个变量的功能是存储一个要变动变量未变动之前的数据的地址
	POINT *tail;

	if(NULL == head || head->next != NULL) {
				return FALSE;
		}
		
		printf("请输入楼号,层数,房间,姓名:");
		scanf("%d%d%d", &pnum, &pceng, &pfang);
		gets(pname);
		
		while(pnum && pceng && pfang) {
			p=(POINT *)calloc(sizeof(POINT), 1);
			p->num=pnum;
			p->ceng=pceng;
			p->fang=pfang;
			strcpy(p->name, pname);
			
			if(NULL == head->next) {
				head->next=p;
			} else {
				tail->next=p;
			}
			tail=p;
			printf("请输入楼号,层数,房间,姓名:");
			scanf("%d%d%d", &pnum, &pceng, &pfang);
			gets(pname);
		}
	return TRUE;
}


void initList(POINT *linkOne) {
	enteringPoints(linkOne);
	printf("\n当前户主信息表为:\n");
	showPointList(*linkOne);
	menu();
}

void menu() {
	printf("\n                                  小区户主信息管理系统\n ");
	printf("  ***********************************************************************************************\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  |      1               2              3              4              5               6 		|\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  |  用户信息插入     用户信息排序    用户信息显示    用户信息删除     用户信息修改    用户信息表销毁  |\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  ***********************************************************************************************\n");
	printf("请输入指令:(输入其他数字表示结束程序)\n");
}

boolean defend() {
	int ok=	0;
	char code[20];               
	int count=0;
	
	printf("                                    安全监测系统\n");
 	printf("            请输入8位密码(初始密码为12345678;两次错误输入后,程序结束):");
	while(!ok && count < 2) {
		gets(code);
		ok=(0 == strcmp(code,"12345678"));
		if (!ok) {
			printf("\n密码错误,");
			++count;
		} else {
			ok = 1;
		}
		if(!ok&&count<2) {
			printf("请再次输入(最后一次机会啦!): ");
		}
	}
	if (ok) {
		printf("\n\1小区管理系统欢迎您\n");
		return TRUE;
	} else {
		printf("很遗憾,程序结束\n");
		return FALSE;
	} 
}

int main() {
	POINT linkOne = {0};
	boolean safe;
	int flag = 1;
	
	printf("制作人: xx专业    xxx\n");
	safe = defend();
	if(safe == FALSE) {
		return 0;
	}

	initList(&linkOne);

	while(flag) {
		flag = function(&linkOne);
	}
	
	return 0;
}

配合前面编写过的 “lhc.h”就可以完成啦。

上面的版本需要多文件联编,不会用命令行编译的同学可能就用不了这个方法,所以,在下方,在本博主改进下,在一个.c文件中直接编译也能运行了:

#include <stdio.h>
#include <malloc.h>
#include <string.h>

typedef unsigned char boolean;
#define TRUE		1
#define FALSE		0

#define KEEP_ON 	1
#define EXIT    	0

typedef struct POINT {
	int num;
	int ceng;
	int fang;
	char name[20];
	struct POINT *next;
}POINT;

boolean defend();
void menu();
void initList(POINT *linkOne);
boolean enteringPoints(POINT *head);
void insertPoint(POINT *head);
POINT *searchPreNode(POINT head, POINT one);
boolean removePoint(POINT *head);
boolean alterPoint(POINT *head);
void showOnePoint(POINT point);
void showPointList(POINT head);
void destoryPointLink(POINT *head);
void sortByRow(POINT head);
int function(POINT *linkOne);

int function(POINT *linkOne) {
	int order;
	int ok;

	scanf("%d",&order);
	switch(order)  {
		case 1: 
			insertPoint(linkOne);
			showPointList(*linkOne);
			break; 
					
		case 2: 
			sortByRow(*linkOne);
			showPointList(*linkOne);
			break; 
					
		case 3: 
			showPointList(*linkOne);
			break; 
					
		case 4: 
			if(TRUE == removePoint(linkOne)) {
				printf("删除结果如下:\n");
				showPointList(*linkOne);
			} else {
				printf("删除失败!\n");
			}
			break; 
					
		case 5: 
			alterPoint(linkOne);
			printf("修改结果如下:\n");
			showPointList(*linkOne);
			break; 
			
		case 6:
			destoryPointLink(linkOne);
			printf("用户信息表已被销毁!!!\n");
			printf("输入1:重新录入信息\n输入其他:终止程序!\n");
			scanf("%d", &ok);
			if(1 != ok) {
				printf("即将终止程序...\n");
				return EXIT;
			}
			initList(linkOne);
			break; 
						
		default : 
			destoryPointLink(linkOne);
			return EXIT;
	}
	printf("\n输入任意继续程序...\n");
	getchar();
	getchar();
	menu();
	return KEEP_ON;
}

void insertPoint(POINT *head) {
	int newNum;
	int newCeng;
	int newFang;
	char newName[20]; 
	int oldNum;
	int oldCeng;
	int oldFang;
	char oldName[20];  
	POINT *p;
	POINT old;
	POINT *pre;


	printf("请输入新用户信息:");
	scanf("%d%d%d", &newNum, &newCeng, &newFang);
	gets(newName);
	p = (POINT *) calloc(sizeof(POINT), 1);
	strcpy(p->name, newName);
	p->num = newNum;
	p->ceng = newCeng;
	p->fang = newFang;
	p->next = NULL;

	printf("请输入指定用户信息:楼号、层数、房间号(实现左插入;若指定用户不存在,则,实现尾随追加):");
	scanf("%d%d%d", &oldNum, &oldCeng, &oldFang);
	old.num = oldNum;
	old.ceng = oldCeng;
	old.fang = oldFang;

	pre = searchPreNode(*head, old);

	if (NULL == pre) {

		pre = head;
	}
	p->next = pre->next;
	pre->next = p;
}

POINT *searchPreNode(POINT head, POINT one) {    
	POINT *p;
	POINT *q = NULL;

	for (p = head.next; p && (p->num != one.num || p->ceng != one.ceng || p->fang != one.fang); p = p->next) {
		q = p;
	}

	return q;    
}

boolean removePoint(POINT *head) {      
	int num;
	int ceng;
	int fang;
	char name[20];
	POINT *pre;
	POINT point;
	POINT *p;


	printf("请输入要删除的用户信息(按照楼号,层数,房间号):");
	scanf("%d%d%d", &num, &ceng, &fang);
	gets(name);
	point.num = num;
	point.ceng = ceng;
	point.fang =fang;
	strcpy(point.name,name);
	pre = searchPreNode(*head, point);
	if (NULL == pre) {
		pre = head;
	} else if (NULL == pre->next) {
		return FALSE;
	}
	p = pre->next;
	pre->next = p->next;
	free(p);

	return TRUE;
}

boolean alterPoint(POINT *head) {     
	int oldnum;
	int oldceng;
	int oldfang;
	char oldname[20];
	int newnum;
	int newceng;
	int newfang;
	char newname[20];
	
	POINT newPoint;
	POINT target;
	POINT *pre;
	
	if(!head) {
		return FALSE;
	}
	
	printf("请输入要修改的用户的信息(按照楼号,层数,房间号,用户名):");
	scanf("%d%d%d", &oldnum, &oldceng, &oldfang); 
	gets(oldname);
	target.num=oldnum;
	target.ceng=oldceng;
	target.fang=oldfang;
	strcpy(target.name,  oldname);
	
	pre = searchPreNode(*head, target);
	if(!pre || NULL !=pre->next ) {
		printf("请输入新的用户信息(按照楼号,层数,房间号,用户名):");
		scanf("%d%d%d", &newnum, &newceng, &newfang); 
		gets(newname);
		pre->next->num=newnum;
		pre->next->ceng=newceng;
		pre->next->fang=newfang;
		strcpy(pre->next->name, newname);
		
		return TRUE;
	} 
	return FALSE;
}

void showOnePoint(POINT point) {
	printf("                                %-d        %-d        %-d        %s         \n",point.num,point.ceng,point.fang,point.name);
}

void showPointList(POINT head) {
	POINT *p;
	printf("\n                           ---------------------------------------------");
	printf("\n                               楼号     层数     房间号     户主姓名\n");
	for (p = head.next; p; p = p->next) {
		showOnePoint(*p);
	}
	printf("                           ---------------------------------------------");
	printf("\n");
}

void destoryPointLink(POINT *head) {
	POINT *p;

	while (head && head->next) {
		p = head->next;
		head->next = p->next;
		free(p);
	}

	head->next = NULL;
}

void sortByRow(POINT head) {
	POINT *pre;
	POINT *next;
	POINT *nextTemp;
	POINT temp;

	for (pre = head.next; pre; pre = pre->next) {
		for (next = pre->next; next; next = next->next) {
			if ((pre->num >= next->num) && (pre->ceng >= next->ceng) && (pre->fang >= next->fang)) {
				temp = *pre;
				*pre = *next;
				*next = temp;

				nextTemp = pre->next;
				pre->next = next->next;
				next->next = nextTemp;
			}
		}
	}
}

boolean enteringPoints(POINT *head) {	
	int pnum;
	int pceng;
	int pfang;
	char pname[20];  //前面这四个变量的定义,是为了将来用户输入以及给链表数据域赋值用的
	
	POINT *p;       //这个变量的功能是存储一个要变动变量未变动之前的数据的地址
	POINT *tail;

	if(NULL == head || head->next != NULL) {
				return FALSE;
		}
		
		printf("请输入楼号,层数,房间,姓名:");
		scanf("%d%d%d", &pnum, &pceng, &pfang);
		gets(pname);
		
		while(pnum && pceng && pfang) {
			p=(POINT *)calloc(sizeof(POINT), 1);
			p->num=pnum;
			p->ceng=pceng;
			p->fang=pfang;
			strcpy(p->name, pname);
			
			if(NULL == head->next) {
				head->next=p;
			} else {
				tail->next=p;
			}
			tail=p;
			printf("请输入楼号,层数,房间,姓名:");
			scanf("%d%d%d", &pnum, &pceng, &pfang);
			gets(pname);
		}
	return TRUE;
}


void initList(POINT *linkOne) {
	enteringPoints(linkOne);
	printf("\n当前户主信息表为:\n");
	showPointList(*linkOne);
	menu();
}

void menu() {
	printf("\n                                  小区户主信息管理系统\n ");
	printf("  ***********************************************************************************************\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  |      1               2              3              4              5               6 		|\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  |  用户信息插入     用户信息排序    用户信息显示    用户信息删除     用户信息修改    用户信息表销毁  |\n");
	printf("  |---------------------------------------------------------------------------------------------|\n");
	printf("  ***********************************************************************************************\n");
	printf("请输入指令:(输入其他数字表示结束程序)\n");
}

boolean defend() {
	int ok=	0;
	char code[20];               
	int count=0;
	
	printf("                                    安全监测系统\n");
 	printf("            请输入8位密码(初始密码为12345678;两次错误输入后,程序结束):");
	while(!ok && count < 2) {
		gets(code);
		ok=(0 == strcmp(code,"12345678"));
		if (!ok) {
			printf("\n密码错误,");
			++count;
		} else {
			ok = 1;
		}
		if(!ok&&count<2) {
			printf("请再次输入(最后一次机会啦!): ");
		}
	}
	if (ok) {
		printf("\n\1小区管理系统欢迎您\n");
		return TRUE;
	} else {
		printf("很遗憾,程序结束\n");
		return FALSE;
	} 
}

int main() {
	POINT linkOne = {0};
	boolean safe;
	int flag = 1;
	
	printf("制作人: xx专业    xxx\n");
	safe = defend();
	if(safe == FALSE) {
		return 0;
	}

	initList(&linkOne);

	while(flag) {
		flag = function(&linkOne);
	}
	
	return 0;
}

这样,运行后结果大致如下图:
在这里插入图片描述在这里插入图片描述
在这里插入图片描述本人就在博文中展示三张图来验证下代码的正确性。
底下这张图片的菜单显示有些乱,本人亲自测试,不同的编译器中,会有不同的显示,有的编译器可能能显示正常形态,若实在不行,就需要观众们自己动手,删点空格,这样就能够更加美观地显示了。

有的同学能发现,其实本人编写的代码和好多搜到的代码的功能函数的参数不一样(如果一样的话,请看解释),这里来做一些解释:
有的版本是传递节点的内容,而不是节点的首地址,但是本人对于这种做法十分不屑,因为我们调用函数时,参数占用的是堆栈空间,这个空间不是很大,而且,若是我们编写的函数是递归函数,那么,很容易造成“栈满溢出”现象,虽然这是个小细节,但是,能学到这里的同学,想必也是将C学到了末尾,或者说已经开始了《数据结构与算法》或者另一种语言的学习,所以,我们要多多关注这些小细节,但是,有时候,用指针也会使得我们的代码出现错误,或者“可读性”变差,所以,我们的编程之路还是很漫长的。

这篇博客写于本人大一下,并且在大一暑假进行了改进,大一下时参加过学校实习,所以了解到大概就是这么个操作,至于文件处理,本人学术浅薄,打算将于今后学懂再写博客,希望这篇博客能对于有需求或是接触链表的朋友们有所帮助。
如有意见,欢迎提出,谢谢!!!

;