单向链表的学习

经验教训:

1. fflush(stdin);

scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
① 遇空格、“回车”、“跳格”键。 ② 遇宽度结束。 ③ 遇非法输入。
键盘缓冲区就可能有残余信息问题。
scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中
解决就要在scanf()函数之后加个fflush(stdin)。

 

2.删除节点后,由于之前建立或添加时申请了内存,此时应用free()函数释放内存。以免引起内存泄露,对内存失去控制,造成内存的浪费的不良影响。

 

3.转义字符\

fp=fopen("F:\\student.txt","w");
在该语句中\\即代表\,文件地址为F:\student.txt,复制后应改为F:\\student.txt。
fp=fopen("student.txt","w");

直接写地址,则在程序文件目录下添加student.txt文件。

 

4. fwrite 和fpintf 区别:

fwrite写的是二进制内容,fprintf写的是数字转换成ASCII码之后的字符。

例如:两者都把数字64写入一个文件,用记事本打开看下,fwrite写的打开是乱码,fprintf写入的是6和4这两个字符。因为fwrite写的是64的二进制表示(4个字节,前面全是0,最后八位是0100000),fprintf写入的实际内容是36H和34H(16进制表示的字符6和字符4的ASCII编码)。

fread 与fscanf同理。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NULL 0

struct student
{
	char name[20];
	int num;
	char sex;
	float score;
	struct student *next;
};

struct student *head = NULL;

//函数声明
void board();//界面
struct student *creat();//创建节点
void add();//添加学生信息
void add_tou();//从头插入
void add_wei();//从尾插入
void add_any();//插入指定位置

void delete_stu();//删除学生信息
void delete_name();//按姓名查找删除
void delete_num();//按学号查找删除

void find();//查找学生信息
void find_name();//按姓名查找
void find_num();//按学号查找
void display_all();//显示所有学生信息

struct student *save(struct student *head);//保存链表数据到文件
struct student *read();//从文件读取链表

int main()
{
	int choice = -1;
	do
		{	
			board();
			printf("请选择功能(0-7):\n");
			scanf("%d",&choice);
			switch(choice)
			{
				case 1: creat();break;
				case 2: add();break;
				case 3: delete_stu();;break;
				case 4: find();break;
				case 5: display_all();break;
				case 6: save(head);break;
				case 7: read();break;
				case 0: exit(0);break;
				default :break;
			}
		}while(choice);

	return 0;
}


void board()//界面
{
	printf("\t\t\t\t学生信息系统\n\n");
	printf("\t\t\t1.创建学生信息链表\n\t\t\t2.添加学生信息\n");
	printf("\t\t\t3.删除学生信息\n\t\t\t4.查找学生信息\n");
	printf("\t\t\t5.显示所有学生信息\n\t\t\t6.保存链表数据到文件\n");
	printf("\t\t\t7.从文件读取链表\n\t\t\t0.退出\n");
}

struct student *creat()//创建节点
{
	struct student *p1,*p2;
	int i,count;
	printf("输入几个学生信息?\n");
	scanf("%d",&count);
	p1=p2=(struct student*)malloc(sizeof(struct student));
	printf("请输入学生姓名 学号 性别 成绩\n");
	scanf("%s %d %c %f",p1->name,&p1->num,&p1->sex,&p1->score);
	fflush(stdin);
	head=p1;
	for(i=1;i<count;i++)
	{
		p1=(struct student*)malloc(sizeof(struct student));
		scanf("%s %d %c %f",p1->name,&p1->num,&p1->sex,&p1->score);
		fflush(stdin);
		p2->next=p1;
		p2=p1;
	}
	p2->next=NULL;
	return head;
}

void add()//添加学生信息
{
	int choice = -1;
	printf("请选择添加位置:1.从头插入 2.从尾插入 3.插入指定位置 0.取消\n");
	scanf("%d",&choice);
	switch(choice)
	{
		case 1: add_tou();break;
		case 2: add_wei();break;
		case 3: add_any();break;
		case 0: break;
		default: add();break;
	}
}
void add_tou()//从头插入
{
	struct student *pnew;
	pnew = (struct student*)malloc(sizeof(struct student));
	printf("请输入需添加的学生姓名 学号 性别 成绩:\n");
	scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score);
	pnew->next = head;
	head = pnew;
}

void add_wei()//从尾插入
{
	struct student *pnew,*pold;
	pnew = (struct student*)malloc(sizeof(struct student));
	printf("请输入需添加的学生姓名 学号 性别 成绩:\n");
	scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score);
	pold = head;
	while(pold->next != NULL)
		pold = pold->next;
	pold->next = pnew;
	pnew->next = NULL;
}

void add_any()//插入指定位置
{
	int weizhi,i;
	struct student *pnew,*pold;
	pnew = (struct student*)malloc(sizeof(struct student));
	printf("请输入需添加的学生姓名 学号 性别 成绩:\n");
	scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score);
	printf("请输入需插入的位置:");
	scanf("%d",&weizhi);
	pold = head;
	for(i=0;i<weizhi-2;i++)
	{
		pold = pold->next;
		if(pold->next == NULL)	//如位置超出人数 则插在队尾
			break;
	}
	pnew->next = pold->next;
	pold->next = pnew;
}

void delete_stu()//删除学生信息
{
	int choice = -1;
	if(head == NULL)
		printf("无学生信息!\n");
	else
	{
		printf("选择删除方式: 1.按姓名查找删除 2.按学号查找删除 0.取消\n");
		scanf("%d",&choice);
		switch(choice)
		{
			case 1: delete_name();break;
			case 2: delete_num();break;
			case 0: break;
			default:delete_stu();break;
		}
	}
}

void delete_name()//按姓名查找删除
{
	struct student *p1,*p2;
	char find_name[20];
	int count = 0;
	printf("请输入需删除的学生姓名:");
	scanf("%s",find_name);
	p1 = head;
	if(strcmp(find_name,head->name) == 0)
	{	printf("学生 %s 信息已成功删除!\n",head->name);
		p1 = head;
		head = head->next;
		free(p1);}		//释放内存
	else
	{
		while(p1 != NULL)
		{
			p2 = p1->next;
			if(strcmp(find_name,p2->name) == 0)
				{	printf("学生 %s 信息已成功删除!\n",p2->name);
					p1->next = p2->next;count++;
					free(p2);break;}		//释放内存
			p1 = p1->next;
		}
		if(count == 0)
			printf("无此学生信息!\n");
	}
}
void delete_num()//按学号查找删除
{
	struct student *p1,*p2;
	int find_num,count = 0;
	printf("请输入需查找的学生学号:");
	scanf("%d",&find_num);
	p1 = head;
	if(find_num == head->num)
	{	printf("学生 %s 信息已成功删除!\n",head->name);
		p1 = head;
		head = head->next;
		free(p1);}		//释放内存
	else
	{
		while(p1 != NULL)
		{
			p2 = p1->next;
			if(find_num == p2->num)
				{	printf("学生 %s 信息已成功删除!\n",p2->name);
					p1->next = p2->next;count++;
					free(p2);break;}	//释放内存
			p1 = p1->next;
		}
		if(count == 0)
			printf("无此学生信息!\n");
	}
}

void find()//查找学生信息
{
	int choice = -1;
	if(head == NULL)
		printf("无学生信息!\n");
	else
	{
		printf("选择查找方式: 1.按姓名查找 2.按学号查找 0.取消\n");
		scanf("%d",&choice);
		switch(choice)
		{
			case 1: find_name();break;
			case 2: find_num();break;
			case 0: break;
			default: find();break;
		}
	}
}

void find_name()//按姓名查找
{
	struct student *p;
	char find_name[20];
	int count = 0;
	printf("请输入需查找的学生姓名:");
	scanf("%s",find_name);
	p = head;
	while(p != NULL)
	{
		if(strcmp(find_name,p->name) == 0)
		{	printf("%s\t%d\t%c\t%.2f\n",p->name,p->num,p->sex,p->score); 
			p = p->next;
			count++;}
		else
			p = p->next;
	}
	if(count == 0)
		printf("查无此人!\n");
}

void find_num()//按学号查找
{
	struct student *p;
	int find_num,count = 0;
	printf("请输入需查找的学生学号:");
	scanf("%d",&find_num);
	p = head;
	while(p != NULL)
	{
		if(p->num == find_num)
		{	printf("%s\t%d\t%c\t%.2f\n",p->name,p->num,p->sex,p->score); 
			p = p->next;
			count++;}
		else
			p = p->next;
	}
	if(count == 0)
		printf("查无此人!\n");
}

void display_all()//显示所有学生信息
{
	struct student *p;
	p=head;
	if(p == NULL)
		printf("无学生信息!\n");
	else{
		printf("学生姓名 学号 性别 成绩:\n");
		while(p != NULL)
		{
			printf("%s\t%d\t%c\t%.2f\n",p->name,p->num,p->sex,p->score);
			p=p->next;
		}
	}
}

struct student *save(struct student *head)//保存链表数据到文件
{   
	struct student *p;  
	FILE *fp;
	p=head;

	if((fp = fopen("student.txt","w")) == NULL)// 易错 \\=\ 
		printf("文件无法打开!\n"); 
	else
		fp=fopen("student.txt","w");	
	while(p != NULL)
	{
		fprintf(fp,"%s\t%d\t%c\t%.2f\n",p->name,p->num,p->sex,p->score);
		p=p->next;
	}
	fclose(fp);
	printf("保存成功!\n");
	return head;
}


struct student *read()//从文件读取链表
{   
	struct student *p1,*p2; 
	FILE *fp;   
	int flag = 1; 
	fp=fopen("student.txt","r");  
	printf("学生姓名 学号 性别 成绩\n");  
	while(!feof(fp))  
	{
		if(flag == 1)   
		{
			p1=(struct student *)malloc(sizeof(struct student));
			head=p1;
			p2=p1;
			fscanf(fp,"%s %d %c %f\n",p1->name,&p1->num,&p1->sex,&p1->score);
			printf("%s\t%d\t%c\t%.2f\n",p1->name,p1->num,p1->sex,p1->score);
			flag--;
		}
		else
		{
			p1=(struct student *)malloc(sizeof(struct student));
			fscanf(fp,"%s %d %c %f\n",p1->name,&p1->num,&p1->sex,&p1->score);
			printf("%s\t%d\t%c\t%.2f\n",p1->name,p1->num,p1->sex,p1->score);
			p2->next=p1;
			p2=p1;
		}
	}
	p2->next = NULL;
	fclose(fp);
	return head; 
}