C语言无头单链表的增删改查以及将链表数据存储到txt文件中

无头单链表即为无头结点单链表其结构如下图所示《C语言无头单链表的增删改查以及将链表数据存储到txt文件中》

即它的首结点存放的有数据

有头结点其结构如下图所示《C语言无头单链表的增删改查以及将链表数据存储到txt文件中》 其首结点是不放数据的 

然后我用到的读写文件的fwrite函数和fread函数想要把链表中的数据存到文件中

写文件:

void Save(LinkList L){
	FILE* fp = fopen("d:/nlist.txt", "wb");
	if (fp == NULL){
		printf("打开存档文件失败!\n");
		return ;
	}
	//使用fwrite往文件里写
	while (L!=NULL){

		fwrite(&L->data, sizeof(L->data), 1, fp);
		L= L->next;
		
	}
	printf("存档成功!\n");
	fclose(fp);
	return;
}

读文件:

void Load(LinkList *L){
	List *p=NULL,*tail=NULL;
	p =tail= *L;
	int i = 1;
	FILE* fp = fopen("d:/nlist.txt", "r");
	if (fp == NULL){
		printf("打开存档文件失败\n");
		return;
	}
	while (1){
		p = (LinkList)malloc(sizeof(List));
		p->next = NULL;
		if (i){//使头指针指向读取的链表的头结点
			size_t n = fread(&p->data, sizeof(p->data), 1, fp);
			if (n == 0){//第一次读没有读到元素
				free(p);
				return;
			}
			else{
				*L = p;
				tail = p;
				p = p->next;
			}
			i--;//除了第一次执行,p就不是头结点了
		}
		else{
			size_t n = fread(&p->data, sizeof(p->data), 1, fp);
				if (n == 0){
				free(p);//我们是先申请空间,再把硬盘上的数据读到申请的结点空间里如果没有读到数据,
						//要把最后申请的这个空间释放掉
				return;
				}
			tail->next = p;
			tail = p;
			p = p->next;
		}
	}
}

读文件时因为要先给你读的是链表元素,要先给读到的元素分配动态的内存空间这时候就要注意:如果没读到元素记得把空间给释放掉

 然后完整的代码如下图所示

#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>
#pragma warning(disable:4996)
typedef struct nlist{
	int data;
	struct nlist *next;
}List, *LinkList;
void menu(){
	printf("	链表使用菜单\n");	
	printf("--------------------------\n");
	printf("1:写入元素(头插式)\n");
	printf("2:写入元素(尾插式)	\n");
	printf("3:查找元素所在位置	\n");
	printf("4:查看链表元素个数	\n");
	printf("5:插入一个元素	\n");
	printf("6:删除某个元素	\n");
	printf("7:按顺序打印元素	\n");
	printf("0:退出	\n");
	printf("---------------------------	\n");
}
void InitList(LinkList *L){
	*L = NULL;
	void Load(LinkList *L);
	Load(L);
}//初始化完毕
void Save(LinkList L){
	FILE* fp = fopen("d:/nlist.txt", "wb");
	if (fp == NULL){
		printf("打开存档文件失败!\n");
		return ;
	}
	//使用fwrite往文件里写
	while (L!=NULL){

		fwrite(&L->data, sizeof(L->data), 1, fp);
		L= L->next;
		
	}
	printf("存档成功!\n");
	fclose(fp);
	return;
}
void Load(LinkList *L){
	List *p=NULL,*tail=NULL;
	p =tail= *L;
	int i = 1;
	FILE* fp = fopen("d:/nlist.txt", "r");
	if (fp == NULL){
		printf("打开存档文件失败\n");
		return;
	}
	while (1){
		p = (LinkList)malloc(sizeof(List));
		p->next = NULL;
		if (i){//使头指针指向读取的链表的头结点
			size_t n = fread(&p->data, sizeof(p->data), 1, fp);
			if (n == 0){//第一次读没有读到元素
				free(p);
				return;
			}
			else{
				*L = p;
				tail = p;
				p = p->next;
			}
			i--;//除了第一次执行,p就不是头结点了
		}
		else{
			size_t n = fread(&p->data, sizeof(p->data), 1, fp);
				if (n == 0){
				free(p);//我们是先申请空间,再把硬盘上的数据读到申请的结点空间里如果没有读到数据,
						//要把最后申请的这个空间释放掉
				return;
				}
			tail->next = p;
			tail = p;
			p = p->next;
		}
	}
}
void CreateFromHead(LinkList* L){
	printf("现在用头插法建立一个无头链表\n请输入要插入的元素个数\n");
	int n;
	scanf("%d", &n);
	if (n < 1){
		printf("插入元素个数错误!\n");
		return ;
	}
	List *head;
	head= (LinkList)malloc(sizeof(List));
	head->next = NULL;
	printf("请输入要写入的元素:\n");
	scanf("%d", &head->data);
	if (*L ==NULL){//使程序在建立完链表后依然可以使用头插法增加多个元素

		*L = head;
	}
	else{
		head->next = *L;
		*L = head;
	}
	while (n-1){
		head = (LinkList)malloc(sizeof(List));
		head->next = NULL;
		printf("请输入要写入的元素:\n");
		scanf("%d", &head->data);
		head->next = *L;
		*L= head;
		n--;
	}
	Save(head);
	return ;
}
void CreateFromTail(LinkList  *L){
	printf("现在使用尾插法插入!\n");
	int n;
	List *tail,*p;
	printf("请输入要插入的元素个数:\n");
	scanf("%d", &n);
	if (n < 1){
		printf("输入元素个数错误!\n");
		return ;
	}
		tail= (LinkList)malloc(sizeof(List));
		tail->next = NULL;
		printf("请输入要写入的元素:\n");
		scanf("%d", &tail->data);
		if (*L == NULL){
			*L = p = tail;
		}
		else{
			p = *L;
			while (p->next != NULL){
				p = p->next;
			}
			p->next = tail;
			p = tail;
		}
	while (n-1){
		tail= (LinkList)malloc(sizeof(List));
		tail->next = NULL;
		printf("请输入要写入的元素:\n");
		scanf("%d", &tail->data);
		p->next = tail;
		p= tail;
		n--;
	}
	Save(*L); 
	return ;
}
void Locate(LinkList L){
	if (L == NULL){
		printf("链表无元素!\n");
		return ;
	}
	printf("请输入要查找的元素的值\n");
	int tar,count=0,len =0;
	List *p2[1024];//
	List *p;
	p = L;
	scanf("%d", &tar);
while(p!=NULL){
		if (p->data == tar){
			
			p2[len] = p;
			count++;
			
		}
		else{
			p2[len] = NULL;
		}
		len++;
		p = p->next;
	}
	printf("共有%d个元素值为%d\n分别在", count,tar);
	for (int i = 0; i < len; i++){
		if (p2[i] != NULL)
			printf("%5d",i);

	}
	printf("\n");
	return ;

}
void ListLen(LinkList L)
{
	List *p;
	p = L;
	int count = 0;
	while (p != NULL){
		count++;
		p = p->next;
	}
	printf("该链表共有%d个元素\n", count);
	return ;
}
void InsList(LinkList *L){
	if (*L == NULL){
		return ;
	}
	printf("请输入要插入元素以及要插入的位置\n");
	int data, tar,site=0;
	scanf("%d %d", &data, &tar);
	List *p, *back, *tarp;
	p = back = *L;
	tarp =( LinkList)malloc(sizeof(List));
	tarp->data = data;
	tarp->next = NULL;
	if (tar <= 0){ 
		printf("插入位置不合法!\n");
		return ;
	}
	else if (tar == 1){
		tarp->next = *L;
		*L = tarp;
		return ;
	}
	while (p != NULL){//p想要指向的是链表中tar-1位置处的结点
		site++;
		if (site == tar - 1){
			break;
		}
		p = p->next;
		if (p == NULL){
			printf("插入位置不合法!big\n");
			return ;
		}
	}
	if (p->next != NULL){
		back = p->next;
		p->next = tarp;
		tarp->next = back;
	}
	else{
		p->next = tarp;
	
	}
	Save(*L);
	return ;


}
void DelList(LinkList *L){//可能要改头指针指向的位置,因此要将头指针的地址传进函数中
	if (*L == NULL){
		return ;
	}
	List *f, *p;
	p=f =* L;
	printf("请输入要删除第几个元素\n");
	int tar;
	scanf("%d", &tar); 
	if (tar <= 0){
		printf("删除位置错误!\n");
		return ;
	}
	else if (tar == 1){
		*L = (*L)->next;
		p->next = NULL;
		free(p);
		return ;
	}
	else{
		f = *L;
		p =( *L)->next;
		for (int i = 0; i < tar-2; i++){
			if (p == NULL){
				printf("删除位置错误!\n");
				return ;
			}
			f = f->next;
			p = p->next;
		}
		if (p->next != NULL){
			f->next = p->next;
			p->next = NULL;
			free(p);
		}
		else{
			f->next = NULL;
			free(p);
		}
		Save(*L);
		return ;

	}
}
void PrintList(LinkList L){
	system("cls");
	menu();
	List * p;
	p = L;
	while (p != NULL){
		printf("%d ->", p->data);
		p = p->next;
	}
	printf("NULL\n");
}
int main(){
	LinkList L;
	InitList(&L);
	menu();
	printf("请输入你要执行的操作序号\n");
	int n;
	scanf("%d", &n);
	while (n){
		switch (n){
		case 1:	CreateFromHead(&L);
			break;
		case 2: CreateFromTail(&L);
			break;
		case 3: Locate(L);
			break;
		case 4:ListLen(L);
			break;
		case 5:InsList(&L);
			break;
		case 6:DelList(&L);
			break;
		case 7:PrintList(L);
			break;
		default: printf("输入命令错误,请重试!\n");
			break;
		}
		printf("请输入你要执行的操作序号\n");
		scanf("%d", &n);

	}
	system("pause");
	return 0;
}

第一次完整写一个无头单链表的完整操作代码,语法难免复杂累赘。欢迎大家的批评指正。以后我会更努力写出简洁的代码的! 

    原文作者:_猪猪快跑
    原文地址: https://blog.csdn.net/m0_56910081/article/details/123952153
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞