简单文件数据库-模拟图书馆管理系统-西安电子科技大学大一程序基础设计课程设计作业

2023-11-08

命令行参数如下:

Libsim –a(-u) xxxx

第一个参数为可执行程序名称;第二个参数为用户身份,-a表示管理员,-u表示读者;第三个参数为用户名

  • 问题分析:

由于无法直接在文件中插入数据(不是简单覆盖),固采用将文件数据提取为链表的方法,对链表进行操作,最后将链表信息导入文件中。

  1. 实现时的困难:
    1. 如何实现管理员和读者双菜单?
    2. 文件该以哪种方式打开?
    3. 文件信息读取不全是什么造成的?
    4. 操作后再读取文件出错,打开文件信息连在一起?
    5. 删除最后一个数据时出错?
    6. 如果用户输入的操作都无效(要修改的信息不存在)怎么办?
  2. 对应解决方案
    1. 判断命令行参数信息,用if判断语句分别进入功能即可。
    2. 操作者只需选择“r(只读)”和“a+(追加)”方式打开文件,防止文件数据意外损失。其中在只有管理员增加数据时才用“a+”,其他模式均以“r”方式打开!
    3. 因为程序有继续操作选项,而上次操作后文件标志已经为EOF,采用rewind函数即可将文件标志位重置
    4. 在写入、修改、删除信息时注意最后写入换行符,保证文件可读性以及下一次操作可行
    5. 因为采用的是链表操作,删除非末尾元素时,下一个链节内容完全拷贝到要删字节,再释放下一个链节即可。但是链表尾指向NULL,访问NULL会出错,要单独考虑。
    6. 定义变量int sign = 0;只有操作有效时sign = 1,进入下一步操作,防止文件信息丢失。
//程序基本配置文件:1.文件名为“book.txt”的文件;2.文件名为“reader.txt”的文件 
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//测试方式选择:1.AUTO:命令行运行;2.标准文件流读入数据;3.手动输入输出数据(用哪个将另外两个#define注释掉即可) 
//#define AUTO
//#define MANUAL1
#define MANUAL2
#define LEN1 sizeof(book_info)
#define LEN2 sizeof(reader_info)
//定义两个结构体,分别存储书本信息和读者借阅信息 
typedef struct Book {
	char code[20];
	char title[100];
	int number;
	struct Book* next;
}book_info;
typedef struct Reader {
	char order[20];
	char name[100];
	char borrow_code[20];
	struct Reader* next;
}reader_info;
const char* book_format = "%s %s %d", * reader_format = "%s %s %s";
char file_name[101] = { 0 };


int main(int argc, char* argv[]) {
	void format_judge(char* type, char* name);
	FILE* open_file();
	void function(char* type, char* name);
	char type[3], name[100];

#ifdef AUTO
	strcpy(type, argv[1]);
	strcpy(name, argv[2]);
#endif
#ifdef MANUAL1
	freopen("in.txt", "r", stdin);
	freopen("out.txt", "w", stdout);
#endif 
#ifdef MANUAL2
	printf("Enter user's type(-a/-u) and username:\n");
	scanf("%s %s", type, name);
#endif 

	//输入参数格式正误判断 
	format_judge(type, name);

	//操作函数 
	function(type, name);

	return 0;
}

//打开文件函数 
FILE* open_file() {
	FILE* fp;
	char  ope_way[3] = { 0 };
	//输入文件名和打开方式 
	printf("Enter the path of data:");
	scanf("%s", file_name);
	//*****注意操作者只需选择“r(只读)”和“a+(追加)”方式打开文件,防止文件数据意外损失!!! 
	printf("Enter the way to operate(r/a+):");
	scanf("%s", ope_way);
	//如果文件不存在,报错 
	if ((fp = fopen(file_name, ope_way)) == NULL) {
		printf("File not exist\n");
		exit(0);
	}
	return fp;
}

//显示文件的所有信息 
void show_file(FILE* fp) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return;
	}

	//文件位置标志重置,以输出完整程序 
	rewind(fp);
	char c;
	//当文件位置为EOF(文件尾) 
	while (!feof(fp)) {
		c = fgetc(fp);
		printf("%c", c);
	}
	printf("\n");
}

//命令行输入参数判断 
void format_judge(char* type, char* name) {
	if (type[0] != '-' || (type[1] != 'a' && type[1] != 'u')) {
		printf("Format Error!\n");
		exit(0);
	}
}

//覆盖文件函数,用于一次操作结束后将新文件内的数据覆盖到老文件上 
//参数列表:指向原文件指针,指向操作产生的新文件的指针 
void revise_file(FILE* fp, FILE* fp_n) {
	if (fp_n == NULL) {
		printf("New file failed to open\n");
		return;
	}
	char c;
	fclose(fp);
	//以“w”方式打开文件,文件原内容擦除 
	fopen(file_name, "w");
	rewind(fp_n);
	//一个字符一个字符地拷贝到原文件中 
	while ((c = fgetc(fp_n)) != EOF) {
		fputc(c, fp);
	}
	fclose(fp);
}

//功能集成函数
//参数列表:用户类型(-a:管理员/-u:用户);用户名 
void function(char* type, char* name) {
	FILE* open_file();
	void add_info(FILE * fp, int object);
	void revise_info(FILE * fp, int object);
	void delete_info(FILE * fp, int object);
	void borrow_book(FILE * fp, FILE * fp_r);
	void return_book(FILE * fp_r);
	void search_info(FILE * fp, FILE * fp_r);

	//定义变量:1.option:操作类型;2.object:操作对象;3.sign:判断是否继续操作标志;4.fp:打开文件指针;5.fp_r:读者信息文件指针 
	int option, object, sign = 1;
	FILE* fp = NULL, * fp_r = NULL;

	//管理员模式 
	if (type[1] == 'a') {
		printf("Administrator, what do you want to do\n\t1.Add information\n\t2.Revise information\n\t3.Delete information\n\t4.Show all the information\nOperate object:\n\t1.book\n\t2.reader\nAnswer:");
		while (sign) {
			scanf("%d%d", &option, &object);
			//进入功能选择,详细见后面各功能函数 
			switch (option) {
			case 1: //增加数据 
			{
				fp = open_file();
				add_info(fp, object);
				break;
			}
			case 2: //修改数据 
			{
				fp = open_file();
				revise_info(fp, object);
				break;
			}
			case 3: //删除数据 
			{
				fp = open_file();
				delete_info(fp, object);
				break;
			}
			case 4: //总览数据 
			{
				if (object == 1) {
					fp = fopen("book.txt", "r");
					show_file(fp);
				}
				else {
					fp_r = fopen("reader.txt", "r");
					show_file(fp_r);
				}
				break;
			}
			default:printf("Option Error\n");
			}
			//是否继续进行操作 
			printf("Continue to operate\n\t1->yes\n\t0->no\nAnswer:");
			scanf("%d", &sign);
		}
		fclose(fp);
		fclose(fp_r);
	}
	//用户模式 
	else {
		printf("User, what do you want to do\n\t1.Borrow books\n\t2.Return books\n\t3.Search information\nAnswer:");
		while (sign) {
			scanf("%d", &option);
			switch (option) {
			case 1: //借书 
			{
				fp = fopen("book.txt", "r");
				fp_r = fopen("reader.txt", "a+");
				if (fp == NULL || fp_r == NULL) {
					printf("File missing\n");
				}
				else borrow_book(fp, fp_r);
				break;
			}
			case 2: //还书 
			{
				fp_r = fopen("reader.txt", "r+");
				strcpy(file_name, "reader.txt\0");
				if (fp_r == NULL) {
					printf("File missing\n");
				}
				else return_book(fp_r);
				break;
			}
			case 3: //查数据 
			{
				fp = fopen("book.txt", "r");
				fp_r = fopen("reader.txt", "r");
				if (fp == NULL || fp_r == NULL) {
					printf("File missing\n");
				}
				else search_info(fp, fp_r);
				break;
			}
			default:printf("Option Error\n");
			}
			printf("Continue to operate\n\t1->yes\n\t0->no\nAnswer:");
			scanf("%d", &sign);
		}
		fclose(fp);
	}
}

//添加数据函数
//参数列表:指向操作文件的指针;操作对象 
void add_info(FILE* fp, int object) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return;
	}
	//定义变量:1.num:操作次数;2.book:添加的图书信息的结构体;3.reader:添加的借阅信息结构体 
	int num;
	book_info book;
	reader_info reader;
	//添加图书信息 
	if (object == 1) {
		printf("How many books you want to add\nAnswer:");
		scanf("%d", &num);
		//提示输入图书信息的格式 
		printf("Information format:book_number title amount\nEnter:\n");
		while (num--) {
			scanf(book_format, &book.code, &book.title, &book.number);
			fprintf(fp, book_format, book.code, book.title, book.number);
			//*****注意添加完后换行! 
			fprintf(fp, "\n");
		}
		printf("Succeed to operate\n");
	}
	//添加借阅者信息 
	else if (object == 2) {
		printf("How many readers you want to add\nAnswer:");
		scanf("%d", &num);
		printf("Information format:reader_number name book_code\nEnter:\n");
		while (num--) {
			scanf(reader_format, &reader.order, &reader.name, &reader.borrow_code);
			fprintf(fp, reader_format, reader.order, reader.name, reader.borrow_code);
			fprintf(fp, "\n");
		}
		printf("Succeed to operate\n");
	}
	else printf("Object error\n");
}

//修改数据函数
//参数列表:指向操作文件的指针;操作对象 
void revise_info(FILE* fp, int object) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return;
	}
	rewind(fp);

	book_info* original_information_input_b(FILE * fp);
	reader_info* original_information_input_r(FILE * fp);
	void information_save_b(book_info * head, FILE * fp_n);
	void information_save_r(reader_info * head, FILE * fp_n);
	book_info* get_adress_b(book_info * head_adress, char* search);
	reader_info* get_adress_r(reader_info * head_adress, char* search);
	void revise_file(FILE * fp, FILE * fp_n);

	//定义变量:1.num:操作数;2.sign:操作是否有效标志;3.search:搜素信息(图书号或书名或读者编号或人名);4.fp_n:指向新文件(存贮操作后的信息)的指针 
	int num, sign = 0;
	char search[100] = { 0 };
	FILE* fp_n = NULL;
	//修改图书信息 
	if (object == 1) {
		//定义变量:1.head:存储了图书信息的链表头;2. book:存贮修改信息的结构体;3.locat:指向修改数据所在链节的指针  
		book_info* head = original_information_input_b(fp), book, * locat;
		printf("How many books you want to revise\nAnswer:");
		scanf("%d", &num);
		while (num--) {
			printf("Enter book_code or title:");
			//输入要找的图书号或书名 
			scanf("%s", search);
			//得到所在链表的位置,如果不存在,locat=NULL,不进行下列操作 
			locat = get_adress_b(head, search);
			if (locat != NULL) {
				printf("Enter the new information(Format:book_number title amount):");
				//输入要用于替换的数据 
				scanf(book_format, &book.code, &book.title, &book.number);
				strcpy(locat->code, book.code);
				strcpy(locat->title, book.title);
				locat->number = book.number;
				//操作有效 
				sign = 1;
			}
		}
		//如果输入的书本都不存在,即操作无效,不进行下列操作,防止书本信息文件内容被清空(revise_file函数有以“w”方式打开文件,文件内容清空) 
		if (sign) {
			//打开存储修改信息的新文件“book_n.txt” 
			fp_n = fopen("book_n.txt", "w+");
			//将链表信息存入新文件 
			information_save_b(head, fp_n);
			//拷贝新文件中信息到原文件 
			revise_file(fp, fp_n);
			printf("Succeed to operate\n");
		}

	}

	if (object == 2) {
		reader_info* head = original_information_input_r(fp), reader, * locat = head;
		//确认是否修改找到信息(针对一个人借多本书的情况) 
		int answer;
		printf("How many readers you want to revise\nAnswer:");
		scanf("%d", &num);
		while (num--) {
			printf("Enter reader_order or name\n:");
			scanf("%s", search);
			while (locat != NULL) {
				//*****得到该读者的第一条信息(注意搜索起点是locat,结合while循环实现搜索所有而非第一个出现的)! 
				locat = get_adress_r(locat, reader.order);
				if (locat != NULL) {
					//输出该条信息的内容 
					printf(reader_format, locat->order, locat->name, locat->borrow_code);
					printf("\nRevise or not\n\t1.yes\n\t2.no\nAnswer:");
					//确认是否修改该条信息 
					scanf("%d", &answer);
					if (answer == 1) {
						printf("Enter the new information(Format:reader_order name borrow_code):\n");
						scanf(reader_format, &reader.order, &reader.name, &reader.borrow_code);
						strcpy(locat->order, reader.order);
						strcpy(locat->name, reader.name);
						strcpy(locat->borrow_code, reader.borrow_code);
						sign = 1;
					}
					//标记为指向下一个 
					locat = locat->next;
				}
			}
		}
		if (sign == 1) {
			fp_n = fopen("reader_n.txt", "w+");
			information_save_r(head, fp_n);
			revise_file(fp, fp_n);
			printf("Succeed to operate\n");
		}
	}

}

//删除数据函数
//参数列表:指向操作文件的指针;操作对象 
void delete_info(FILE* fp, int object) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return;
	}
	rewind(fp);

	book_info* original_information_input_b(FILE * fp);
	reader_info* original_information_input_r(FILE * fp);
	book_info* get_adress_b(book_info * head_adress, char* search);
	reader_info* get_adress_r(reader_info * head_adress, char* search);
	void information_save_b(book_info * head, FILE * fp_n);
	void information_save_r(reader_info * head, FILE * fp_n);
	void revise_file(FILE * fp, FILE * fp_n);

	int num, answer, sign = 0;
	char search[100];

	if (object == 1) {
		//定义变量:3.free_adress:指向要删除数据链节的指针 
		book_info* head = original_information_input_b(fp), * locat = NULL, * free_adress = NULL;
		printf("How many books you want to delete\nAnswer:");
		scanf("%d", &num);
		while (num--) {
			printf("Search book_code or title to delete:");
			scanf("%s", search);
			locat = get_adress_b(head, search);
			//删除链节的方式采用复制——释放法,即将下一个链节内容完全拷贝到要删字节,再释放下一个链节 
			if (locat != NULL) {
				//不是链表尾的情况 
				if (locat->next != NULL) {
					free_adress = locat->next;
					*locat = *(locat->next);
					free(free_adress);
				}
				//*****链表尾的情况!(locat->next=NULL!访问会出错!) 
				else {
					book_info* taget = head;
					//找到要删链节的上一个链节 
					for (; taget->next != locat; taget = taget->next);
					//将上一个链节的指向该为NULL,即可去除原先链表尾 
					taget->next = NULL;
					free(locat);
				}
				sign = 1;
			}
		}
		if (sign) {
			FILE* fp_n = fopen("book_n.txt", "w+");
			information_save_b(head, fp_n);
			revise_file(fp, fp_n);
			printf("Succeed to operate\n");
		}
	}

	//删除读者信息,基本和修改读者信息部分相同 
	if (object == 2) {
		reader_info* head = original_information_input_r(fp), * locat = head, * free_adress = NULL;
		printf("How many readers you want to delete\nAnswer:");
		scanf("%d", &num);
		while (num--) {
			printf("Search reader_order or name to delete:");
			scanf("%s", search);
			while (locat != NULL) {
				locat = get_adress_r(locat, search);
				if (locat != NULL) {
					printf("This person's one record:");
					printf(reader_format, locat->order, locat->name, locat->borrow_code);
					printf("\nDelelt this record or not?\n\t1.yes\n\t2.no\nAnswer:");
					scanf("%d", &answer);
					if (answer == 1) {
						if (locat->next != NULL) {
							free_adress = locat->next;
							*locat = *(locat->next);
							free(free_adress);
						}
						else {
							reader_info* taget = head;
							for (; taget->next != locat; taget = taget->next);
							taget->next = NULL;
							free(locat);
						}
						sign = 1;
					}
					locat = locat->next;
				}
			}
		}
		if (sign) {
			FILE* fp_n = fopen("reader_n.txt", "w+");
			information_save_r(head, fp_n);
			revise_file(fp, fp_n);
			printf("Succeed to operate\n");
		}
	}
}

//借书函数 
//参数列表:指向图书信息文件的指针;指向读者信息文件的指针 
void borrow_book(FILE* fp, FILE* fp_r) {
	if (fp == NULL || fp_r == NULL) {
		printf("File failed to open\n");
		return;
	}
	rewind(fp);

	book_info* original_information_input_b(FILE * fp);
	book_info* get_adress_b(book_info * head_adress, char* search);

	int num, answer;
	char search[100];
	book_info* head = original_information_input_b(fp), * locat;

	//询问是否列出馆藏图书列表 
	printf("Show book list\n\t1.yes\n\t2.no\nAnswer:");
	scanf("%d", &answer);
	if (answer == 1)show_file(fp);
	printf("How many books you want to borrow\nAnswer:");
	scanf("%d", &num);
	while (num--) {
		printf("Search book_code or title to borrow:");
		scanf("%s", search);
		locat = get_adress_b(head, search);
		if (locat != NULL) {
			char order[20], name[100];
			printf("Enter your personal_order and your name:");
			scanf("%s%s", order, name);
			//将借阅信息存储到读者信息文件 
			fprintf(fp_r, reader_format, order, name, locat->code);
			fprintf(fp_r, "\n");
			printf("Succeed to operate\n");
		}
	}
}

//还书函数
//参数列表:指向读者信息文件的指针 
void return_book(FILE* fp) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return;
	}
	rewind(fp);

	reader_info* original_information_input_r(FILE * fp);
	reader_info* get_adress_r(reader_info * head_adress, char* search);
	void information_save_r(reader_info * head, FILE * fp_n);

	int num, sign = 0;
	reader_info reader, * head = original_information_input_r(fp), * locat = head;

	printf("How many books you want to return\nAnswer:");
	scanf("%d", &num);
	while (num--) {
		printf("Enter your person_order name and book_code:");
		scanf(reader_format, reader.order, reader.name, reader.borrow_code);
		//*****同时判断读者编号和姓名是否符合,直到链表尾 (注意下一次搜寻的起始地址为locat->next!)
		for (; locat != NULL && strcmp(locat->order, reader.order) != 0; locat = get_adress_r(locat->next, reader.name));
		if (locat != NULL) {
			if (locat->next != NULL) {
				reader_info* free_adress = locat->next;
				*locat = *(locat->next);
				free(free_adress);
			}
			else {
				reader_info* taget = head;
				for (; taget->next != locat; taget = taget->next);
				taget->next = NULL;
				free(locat);
			}
			sign = 1;
		}
		else printf("Record doesn't exist\n");
	}
	if (sign) {
		FILE* fp_n = fopen("reader_n.txt", "w+");
		information_save_r(head, fp_n);
		revise_file(fp, fp_n);
		printf("Succeed to operate\n");
	}

}

//查数据函数
//参数列表:指向图书信息文件的指针;指向读者信息文件的指针 
void search_info(FILE* fp, FILE* fp_r) {
	book_info* original_information_input_b(FILE * fp);
	reader_info* original_information_input_r(FILE * fp);
	book_info* get_adress_b(book_info * head_adress, char* search);
	reader_info* get_adress_r(reader_info * head_adress, char* search);

	int answer, num, i = 1;
	char search[100];
	printf("Want to know what\n\t1.Show all books\n\t2.Search one book\n\t3.Remain to return\nAnswer:");
	scanf("%d", &answer);
	//展示所有馆藏图书 
	if (answer == 1) show_file(fp);
	//输入图书号或书名看有没有 
	else if (answer == 2) {
		book_info* head = original_information_input_b(fp);
		printf("How many books you want to search\nAnswer:");
		scanf("%d", &num);
		while (num--) {
			printf("Search book_code or title to show:");
			scanf("%s", search);
			book_info* locat = get_adress_b(head, search);
			if (locat != NULL) {
				printf(book_format, locat->code, locat->title, locat->number);
				printf("\n");
				reader_info* head_r = original_information_input_r(fp_r), * locat_r = head_r;
				printf("Borrow record:\n");
				for (i = 1; locat_r != NULL; locat_r = locat_r->next, i++) {
					if (strcmp(locat->code, locat_r->borrow_code) == 0)
						printf("%d : %s %s\n", i, locat_r->order, locat_r->name);
				}
			}
		}
	}
	//输入个人信息查找待还图书 
	else if (answer == 3) {
		reader_info reader, * head = original_information_input_r(fp_r), * locat = head;
		printf("Enter your personal_order and name:");
		scanf("%s%s", reader.order, reader.name);
		while (locat != NULL) {
			for (; locat != NULL && strcmp(locat->name, reader.name) != 0 && strcmp(locat->order, reader.order) != 0; locat = get_adress_r(locat->next, reader.order));
			if (locat == NULL)break;
			else {
				printf("Borrowed book %d:", i++);
				printf("%s", locat->borrow_code);
				printf("\n");
				locat = locat->next;
			}
		}

	}

}

//创建链表函数,将图书信息文件提取成链表
//参数列表:指向图书信息文件指针;返回值:链表链头 
book_info* original_information_input_b(FILE* fp) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return NULL;
	}
	//定义变量:1.head:链表头;2.当前链表操作位置指针;3.暂存数据的结构体 
	book_info* head = NULL, * p = NULL, temp;
	int i = 0;
	//从文件中读取信息直道文件尾 
	while (fscanf(fp, book_format, &temp.code, &temp.title, &temp.number) != EOF) {
		i++;
		//如果是链表头,开辟空间地址即为head,不是表头则依照赋值表达式的右结合性将链表进行延伸 
		if (i == 1)head = p = (book_info*)malloc(LEN1);
		else p = p->next = (book_info*)malloc(LEN1);

		strcpy(p->code, temp.code);
		strcpy(p->title, temp.title);
		p->number = temp.number;

	}
	//链表尾部处理 
	if (i != 0)p->next = NULL;
	return head;
}

//创建链表函数,将读者信息文件提取成链表
//参数列表:指向读者信息文件指针 返回值:链表链头
reader_info* original_information_input_r(FILE* fp) {
	if (fp == NULL) {
		printf("File failed to open\n");
		return NULL;
	}
	reader_info* head = NULL, * p = NULL, temp;
	int i = 0;

	while (fscanf(fp, reader_format, &temp.order, &temp.name, &temp.borrow_code) != EOF) {

		i++;
		if (i == 1)head = p = (reader_info*)malloc(LEN2);
		else p = p->next = (reader_info*)malloc(LEN2);

		strcpy(p->order, temp.order);
		strcpy(p->name, temp.name);
		strcpy(p->borrow_code, temp.borrow_code);

	}

	if (i != 0)p->next = NULL;
	return head;
}

//保存链表信息函数,将图书信息链表保存到新文件中 
//参数列表:指向图书信息新文件指针 
void information_save_b(book_info* head, FILE* fp_n) {
	book_info* p = head;
	for (; p != NULL; p = p->next) {
		fprintf(fp_n, book_format, p->code, p->title, p->number);
		fprintf(fp_n, "\n");
	}
}

//保存链表信息函数,将读者信息链表保存到新文件中 
//参数列表:指向读者信息新文件指针 
void information_save_r(reader_info* head, FILE* fp_n) {
	reader_info* p = head;
	for (; p != NULL; p = p->next) {
		fprintf(fp_n, reader_format, p->order, p->name, p->borrow_code);
		fprintf(fp_n, "\n");
	}
}

//搜索信息函数 
//参数列表:指向图书信息新文件指针 返回值:所找链节地址,无返回NULL 
book_info* get_adress_b(book_info* head_adress, char* search) {
	//定义变量:1.search_adress:当前搜索链节地址 
	book_info* search_adress = head_adress;
	//先对图书号进行匹配,是否满足输入的信息 
	for (; search_adress != NULL && strcmp(search_adress->code, search) != 0; search_adress = search_adress->next);
	//如果没有,重置当前搜索地址,再和书名进行匹配 
	if (search_adress == NULL) {
		for (search_adress = head_adress; search_adress != NULL && strcmp(search_adress->title, search) != 0; search_adress = search_adress->next);
		if (search_adress != NULL)	return search_adress;
		else {
			printf("This book doesn't exist\n");
			return NULL;
		}
	}
	else return search_adress;
}

//搜索信息函数
//参数列表:指向读者信息新文件指针 返回值:所找链节地址,无返回NULL
reader_info* get_adress_r(reader_info* head_adress, char* search) {
	reader_info* search_adress = head_adress;
	for (; search_adress != NULL && strcmp(search_adress->order, search) != 0; search_adress = search_adress->next);
	if (search_adress == NULL) {
		for (search_adress = head_adress; search_adress != NULL && strcmp(search_adress->name, search) != 0; search_adress = search_adress->next);
		if (search_adress != NULL)	return search_adress;
		else {
			printf("This person doesn't exist\n");
			return NULL;
		}
	}
	else return search_adress;

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

简单文件数据库-模拟图书馆管理系统-西安电子科技大学大一程序基础设计课程设计作业 的相关文章

  • X11 模式对话框

    如何使用 Xlib 在 X11 中创建模式对话框 模态对话框是一个位于应用程序其他窗口之上的窗口 就像瞬态窗口一样 并且拒绝将焦点给予应用程序的其他窗口 在 Windows 中 当试图从模态窗口夺取焦点时 模态也会通过闪 烁模态窗口的标题栏
  • fopen_s 怎么会比 fopen 更安全呢?

    我正在处理遗留代码Windows平台 当我编译代码时VS2013 它给出以下警告 错误 C4996 fopen 该函数或变量可能不安全 考虑使用fopen s反而 要禁用弃用 请使用 CRT SECURE NO WARNINGS 详情请参见
  • 是否有可能劫持标准输出

    我正在尝试使用 C 重定向 Windows XP 上已运行进程的标准输出 我知道如果我自己生成进程 我可以做到这一点 但对于这个应用程序 我更喜欢一个 监听器 我可以附加到另一个进程 这在纯 Net 中可能吗 如果不可能 在 Win32 中
  • Caliburn.Micro - ShowDialog() 如何关闭对话框?

    EDIT 新信息 刚刚设法让记录器工作 老实说 我不知道 cm 有一个 并且在尝试使用时收到此消息TryClose TryClose requires a parent IConductor or a view with a Close m
  • 如何在特定时间以毫秒精度触发 C# 函数?

    我有两台计算机 它们的时间通过 NTP 同步 确保时间仅相差几毫秒 其中一台计算机将通过 TCP 向另一台计算机发送一条消息 以在两台计算机上的未来指定时间启动某个 c 函数 我的问题是 如何在特定时间以毫秒精度 或更好 触发 C 中的函数
  • 将公历日期转换为儒略日期,然后再转换回来(随着时间)

    我正在编写一个程序 必须将当前的公历日期和时间转换为儒略日期 然后再转换回公历门 最终我需要添加能够添加年 月 日 小时 分钟和秒的功能 但我需要先解决这部分问题 现在我已经从公历日期转换为儒略日期 所以从逻辑上讲 我觉得我应该能够以某种方
  • 最新 .Net MongoDb.Driver 的连接问题

    我创建了一个 MongoLab 沙箱数据库 我与 MongoChef 连接 效果很好 我通过 Nuget 安装了 MongoDB Driver 2 2 2 我编写了一些简单的 C 演示代码 但就是无法使其工作 连接字符串是直接从 Mongo
  • 如何从 Qt 应用程序通过 ODBC 连接到 MySQL 数据库?

    我有一个新安装的 MySQL 服务器 它监听 localhost 3306 从 Qt 应用程序连接到它的正确方法是什么 原来我需要将MySQL添加到ODBC数据源 我在遵循这个视频教程后做到了这一点 https youtu be K3GZi
  • 嵌入资源文件的路径

    我的资源文件中有一个图标 我想引用它 这是需要图标文件路径的代码 IWshRuntimeLibrary IWshShortcut MyShortcut MyShortcut IWshRuntimeLibrary IWshShortcut W
  • 无法加载程序集问题

    我收到以下错误 无法加载程序集 错误详细信息 System BadImageFormatException 无法加载文件或程序集 文件 或其依赖项之一 该程序集是由比当前加载的运行时更新的运行时构建的 无法加载 该程序集是使用 Net Fr
  • opencv中如何去除二值图像噪声?

    将图像转换为二值图像 黑白 后如果有任何噪音怎么办 我消除了那些不需要的噪音 您可以看到下图的黑色区域内有一些白噪声 我该如何去除噪声 使用opencv http img857 imageshack us img857 999 blackn
  • Linq 合并列表

    我的课 public class Foo public int A get set public List
  • 在c#中获取没有时间的日期

    我的表上有一列 缺勤日期时间 日期 当我想要获取包含日期的行时 它返回 0 行 这是我的 C 代码 DateTime ClassDate DateTime Parse lblDate Content ToString var Abs dbs
  • 您对“大规模 C++ 软件设计”的看法 [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 正在阅读亚马逊评论 https rads stackoverflow com amzn click com 0201633620 and ACC
  • DataGridView 行背景颜色没有改变

    我想根据加载时的特定条件更改 DGV 行的背景颜色 即使在 Windows 窗体中也是如此 但我看不到任何 DGV 行的颜色有任何变化 谁能告诉我如何解决这个问题 private void frmSecondaryPumps Load ob
  • 如何在 C# 中更改公共 IP 地址

    我正在创建一个 C winform 应用程序 我想在其中更改公共 IP 地址 而不是像 Hotspot Shield ZenMate OpenVPN 等那样更改 IPv4 地址 我已经检查了以下链接 但没有找到足够的帮助 所以我发布了这个问
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • 如何将System.Windows dll添加到Visual Studio 2010 Express?

    我正在开发一个小型应用程序C and VS2010 as IDE with NET框架4 我想用CaptureSource类以便从笔记本电脑的网络摄像头捕获视频 为此我需要添加一个命名空间System Windows DependencyO
  • 卸载程序

    我正在尝试使用此代码卸载程序 但它似乎不起作用 我尝试过其他答案 但似乎也不起作用 有人可以帮助我吗 我正在尝试按给定名称 displayName 卸载该程序 例如 我给出 displayName Appname 那么此代码应该从我的计算机
  • 如何使用 C# 为 azure devops 变量赋值

    我有 selenium C 测试脚本 可以从浏览器获取令牌 我有两个 azure devops 任务 一个用于执行 selenium 测试 另一个用于执行 API 测试 我想将 selenium 测试获取的令牌传递给 API 测试执行任务

随机推荐

  • Linux系统管理员非常使用的几款工具推荐

    1 ExplainShell com 命令解释 对于Linux用户来说每天都会写各种命令和脚本 那么你可以使用这个网站工具来查看命令式如何工作的 这样可以避免不必要的错误出现 也是一个很好的学习命令的方式 2 BashrcGenerator
  • 使用 Builder 构建对象

    遇到多个构造器参数时 要考虑使用构建器 当遇到成员变量较多的类时 使用构造方法初始化对象会使得代码的可读性以及规范性变差 比如想知道某个参数的含义时必须要查看构造方法的定义源码 而且如果不消息颠倒了参数的顺序 编译器可能也不会报错 可以使用
  • 【Java集合 4】java character

    Java学习路线 搬砖工逆袭Java架构师 简介 Java领域优质创作者 CSDN哪吒公众号作者 Java架构师奋斗者 扫描主页左侧二维码 加入群聊 一起学习 一起进步 欢迎点赞 收藏 留言 目录 一 前言 二 ASCII控制字符 三 AS
  • Oracle数据库的启动

    lsnrctl start 启动监听 sqlplus nolog SQL gt conn as sysdba SQL gt startup 启动数据
  • 提高性能 MSSQL百万数据量 值得注意的30条优化技巧

    1 对查询进行优化 应尽量避免全表扫描 首先应考虑在 where 及 order by 涉及的列上建立索引 2 应尽量避免在 where 子句中对字段进行 null 值判断 否则将导致引擎放弃使用索引而进行全表扫描 如 select id
  • JSP动态网页开发技术

    一 学习目标 1 JSP概述 2 JSP指令 3 JSP 隐式对象 二 重点知识 1 JSP概述 JSP是什么 1 JSP全称Java Server Pages 是一种动态网页开发技术 它使用JSP标签在HTML网页中插入Java代码 标签
  • android控制电脑,安卓手机远程控制电脑教程详解

    当我们出门在外 没有电脑在身边 但又急需远程处理电脑上的事务时 怎么办呢 自从锤子出了手机远程协助后 没有锤子的人就急了 这里有个可以让所有Android手机和ios手机实现远程协助功能的小技巧 能 远程控制 远程控制 远程控制 windo
  • 初始gensim

    1 import jieba 2 import gensim 3 from gensim import corpora 4 from gensim import models 5 from gensim import similaritie
  • 复制CSDN文章,去掉代码前面行号的方法(及一些正则表达式小技巧)

    分享一些平时工作中常用的正则表达式小技巧 一 去掉代码前面行号的方法 idongchen modify 2018 12 5 csdn的markdown解析器蛮恶心的文章整体复制下来总有行号在前面 可以用正则找到这些行号给去掉就好 带点的 s
  • sqli-labs(29-31)

    序 这三关都是双服务器问题 网上很多教程都只考虑了apache 其实是php apache jsp tomcat 环境的搭建已经写在了另外一篇博客中 这里再推荐一下一个大牛写得很好的博客 里面把每关的原理都讲得很清晰 但是他里面关于本关的原
  • CV-对比学习-模型:MoCo/SimCLR/BYOL/SimSiam

    很多大佬认为 深度学习的本质就是做两件事情 Representation Learning 表示学习 和 Inductive Bias Learning 归纳偏好学习 在表示学习方面 如果直接对语义进行监督学习 虽然表现很好 但是它需要很多
  • lvs负载均衡、LVS集群部署

    四 LVS集群部署 lvs给nginx做负载均衡项目 218lvs DR 负载均衡器 yum y install ipvsadm 安装这个工具来管理lvs 设置VIP192 168 142 120 创建ipvsadm的文件用来存放lvs的规
  • c语言 如何创建txt文件,C++文本文件读写操作详解

    前面章节中 已经给大家介绍了文件流对象如何调用 open 方法打开文件 并且在读写 又称 I O 文件操作结束后 应调用 close 方法关闭先前打开的文件 那么 如何实现对文件内容的读写呢 接下来就对此问题做详细的讲解 在讲解具体读写文件
  • MySQL基础---连接查询(等值连接与非等值连接)

    多个表格查询 笛卡尔乘积现象 表1有m行 表2 有n行 结果有m n行 发生原因在于没有有效的连接条件 如何避免 添加有效的连接条件 方法 分类方法 按照年代分类 sql192标准和sql199标准 功能 内链接 等值连接 非等值连接 自连
  • 学习日记——物联网云平台(乐鑫云平台)

    物联网云平台了解 1 物联网云平台 接收设备上报的数据 向设备下发数据 对数据进行转发 分析 计算 显示 管理设备等 2 常见的物联网云平台一般有 私有物联网云平台 假设某瓜农 为瓜棚装上了物联网温湿计 温湿度数据通过网络发送某台主机 这台
  • redis--11.1--操作--对列表类型,集合类型,有序集合类型进行键排序

    redis 11 1 操作 对列表类型 集合类型 有序集合类型进行键排序 1 命令 sort key alpha BY pattern LIMIT offset count GET pattern GET pattern asc desc
  • javax.validation.constraints注解

    文章目录 概要 常用的注解 其他注解 小结 概要 javax validation constraints是Java Validation API中的一个包 它提供了一组注解 用于在Java代码中进行数据校验和验证 该包中定义了多个注解 用
  • LR(1)分析表-语法树-四元式

    这学期的编译原理终于学完了 不愧是号称最难的科目 要用C 从头到尾实现一下小型编译器 还真不容易啊 不过总算是做完了 首先上文法 这个文法是根据上一篇博客简化的 但还是有一点问题的 暂时发现有一个地方不符合LR1的规则 函数的返回类型如果是
  • 【ACOUG】Oracle技术爱好者的乐园

    ACOUG 的含义为 All China Oracle User Group http www acoug org 该组织是为了更好的提供一个Oracle用户的交流和活动平台 组织和发起一些公益性质的活动 这个组织是Eygle和Kamus发
  • 简单文件数据库-模拟图书馆管理系统-西安电子科技大学大一程序基础设计课程设计作业

    命令行参数如下 Libsim a u xxxx 第一个参数为可执行程序名称 第二个参数为用户身份 a表示管理员 u表示读者 第三个参数为用户名 问题分析 由于无法直接在文件中插入数据 不是简单覆盖 固采用将文件数据提取为链表的方法 对链表进