【C语言期末项目-通讯录】-终级版本-可动态申请内存、可存储数据到文件(手把手详细过程,期末评分A+的项目,答辩辅助神博文,建议三连点赞收藏)

目录

​编辑

前言:

 1.项目功能需求分析 

2.文件框架说明 

3.程序主框架实现 

4.创建联系人结构体类型和通讯录结构体类型 

4.1创建通讯录 

5.程序功能实现--封装功能函数实现不同功能 

5.1通讯录初始化

 5.2增加联系人 

 5.3显示所有联系人的信息

5.4删除指定联系人的信息 

5.5查找指定联系人 

 5.6修改联系人的信息

 6.释放通讯录

7.保存通讯录信息

8.源码及结语


前言:

对于这个项目,是前面数组基础版本的通讯录的升级版本,大家如果一步理解有困难,一定先点击我的主页了解一下前几篇博客的内容做一个铺垫,我这里罗列一下关联最大的几篇:

①动态内存详解

②通讯录基础数组版本

③C语言结构体详解

C语言文件详解

 1.项目功能需求分析 

实现一个通讯录:
通讯录保存个人信息

 名字,年龄 性别 电话 住址    用保存人的信息的结构体实现

1.通讯录空间不固定,可以先存放一部分的信息,当用户还要存入信息的时候可以自动增加容量。

(比如默认先存放3个联系人的信息,不够了,就每次增加两个联系人信息的空间给用户)
 2.添加联系人
3.删除指定联系人
4.查找指定联系人
5.显示所有人的信息
6.排序功能

7.可以修改指定联系人的信息

8.退出程序后,录入的信息可以保存在硬盘文件中,下次打开通讯录程序还可以查询到。

2.文件框架说明 

test.c 主菜单文件,用于功能测试

contact.c 函数具体实现文件

contact.h 存放函数和类型的声明和必要头文件

3.程序主框架实现 

我们希望在程序中实现不同的操作,比如上述的增删查改联系人的信息,而不是执行一次程序就结束,用户可以选择退出。接下来我们就实现一下主体框架,包含主页面菜单显示。

void menu()
{printf("----------------------------------\n");printf("|***0.Exit       1.ADD***********|\n");printf("|***2.DEL       3.SEARCH*********|\n");printf("|***4.MODIFY    5.SHOW***********|\n");printf("|***6.SORT       ****************|\n");printf("----------------------------------\n");}
void test()
{int  input = 0;do{menu();printf("请选择:》");scanf("%d", &input);switch (input){case 1:break;case 2:break;case 3:break;case 4:break;case 5:break;case 6:break;case 0:printf("退出程序成功\n");break;default:printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");break;}} while (input);
}int main()
{test();return 0;
}

case后面的选项是1,2,3,4,5,那么我们想可不可以利用枚举,让case后面的选项既能表示我们的功能含义又能表示功能选择数字,这样的代码可读性就会更高一些,我们就可以修改如下 :

首先定义选择枚举类型:

enum OPtion
{EXIT,//0ADD,//1DEL,//2SEARCH,MODIFY,SHOW,SORT};

这个依然是放在我们的头文件中去定义,这样代码的整体美观些,接下来的结构修改为:

void menu()
{printf("----------------------------------\n");printf("|***0.Exit       1.ADD***********|\n");printf("|***2.DEL       3.SEARCH*********|\n");printf("|***4.MODIFY    5.SHOW***********|\n");printf("|***6.SORT       ****************|\n");printf("----------------------------------\n");}
void test()
{int  input = 0;Contact con;InitContact(&con);do{menu();printf("请选择:》");scanf("%d", &input);switch (input){case ADD:break;case DEL:break;case SEARCH:break;case MODIFY:break;case SHOW:break;case SORT:break;case EXIT:printf("退出程序成功\n");break;default:printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");break;}} while (input);
}int main()
{test();return 0;
}

4.创建联系人结构体类型和通讯录结构体类型 

由于通讯录存储的是每一个联系人的基本信息,名字、电话、性别、住址等,所以我们可以封装一个联系人结构体类型用于描述每一个联系人。

typedef struct PeoInfo
{char name[20];int age;char sex[5];char telepnumber[12];char addr[30];} PeoInfo;

为了后续书写的方便将struct PeoInfo类型重定义为PeoInfo

我们现在需要一块空间来存储我们联系人的信息,这块空间的起始地址交给我们的一个联系人结构体类型的指针。

PeoInfo* data;//指向了存放数据的空间

由于,我们后续会对通讯录进行增删操作,就会改变数组的大小,为了方便查看或者显示或者为了方便操作我们可以定义一个SZ来记录数组的大小,增加一个联系人,sz+1.......

int sz;//记录的是当前有效元素的个数

这,当我们起始有三个联系人类型那么大的空间的时候,还没有存入联系人的信息,此时我们的sz=0,那么我们什么时候开始扩大我们的空间呢,所以我们专门设计一个变量来记录我们通讯录的数据空间容量,起始容量为3,当sz 等于我们的容量的时候,就可以扩容了。

int  capacity;//记录当前存放数据空间的容量

数据区,容量和联系人数目都是通讯录的属性,我们可以设计一下通讯录类型结构体:

typedef struct Contact
{PeoInfo* data;//指向了存放数据的空间int sz;//记录的是当前有效元素的个数int  capacity;//记录当前存放数据空间的容量}Contact;

为了以后书写方便,用typedef重定义通讯录结构体类型为:Contact类型。

4.1创建通讯录 

当我们的通讯录类型有了过后,我们就可以创建一个通讯录:

5.程序功能实现--封装功能函数实现不同功能 

5.1通讯录初始化

初始化函数,首先要为我们的data数据区申请3个PeoINfo类型的空间,将sz也初始化为0.将容量初始化3,起始的容量不一定设置为3,方便不同的伙伴来设置,我们将容量的大小也设置为宏.我们传参使用了结构体地址传参,接收参数使用了结构体指针,内存占用少。

void Initcontact(Contact* pc)
{assert(pc);pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));if (pc->data == NULL){perror("Initcontact");}pc->sz = 0;pc->capacity = CAPICITY;
}

②由于我们的数据后续是要存储到我们的文件中的,那么就意味着当我们启动程序的时候是不是应该先把文件中的数据加载到程序中来,所以我们还需要实现一个加载函数,将文件中的数据读到我们的程序中来。

int ChekCapacity(Contact* pc);//提前声明我们的检查增容函数
void LoadContact(Contact* pc)
{//首先用二进制读的方式打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){//打开失败就不继续了perror("loadcontact");return;}//读文件PeoInfo tmp = { 0 };//创建一个联系人结构体来存储读到的信息while (fread(&tmp, sizeof(PeoInfo), 1, pf))//fred返回的是读到的个数,读完返回0{if (0 == ChekCapacity(pc))//这里因为要把读到的信息放到通讯录中,就要考虑增容return;//增容失败就不往下执行了//增容成功,将数据加载到通讯录pc->data[pc->sz] = tmp;pc->sz++;//加载一个联系人信息,sz++}//关闭文件fclose(pf);pf = NULL;}
void Initcontact(Contact* pc)

放到最后将通讯录信息保存写完后一起测试。

 5.2增加联系人 

在动态版本中,我们不用考虑通讯录满没满。而是应该考虑通讯录申请的空间是否够了,不够就要扩容,每录入一个联系的信息,sz就+1,当我们的sz与我们的容量相等的时候,就要考虑扩容,所以我们进入增加函数第一步就应该先判断是否要增容。

为了代码方便,我们将检查是否要增容这一步封装为一个函数:

int ChekCapacity(Contact* pc)
{if (pc->sz == pc->capacity){PeoInfo* ptr =(PeoInfo * )realloc(pc->data, (pc->capacity + 2 * sizeof(PeoInfo)));if (ptr == NULL){perror("ChekCapaticy");return  0;}else{pc->data = ptr;pc->capacity += 2;}}return 1;
}

函数返回1,说明增容成功,函数返回0说明增容失败。当然,也不一定每次只增加两个空间,我们还是将增加的空间数目定义为宏,方便伙伴们修改:

#define ADDC 2
void Initcontact(Contact* pc)
{assert(pc);pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));if (pc->data == NULL){perror("Initcontact");}pc->sz = 0;pc->capacity = CAPICITY;
}
int ChekCapacity(Contact* pc)
{if (pc->sz == pc->capacity){PeoInfo* ptr =(PeoInfo * )realloc(pc->data, (pc->capacity + ADDC * sizeof(PeoInfo)));if (ptr == NULL){perror("ChekCapaticy");return  0;}else{pc->data = ptr;pc->capacity += ADDC;printf("增容成功\n");
return1;}}return 1;
}

我们的增加联系人的函数为:

void AddContact(Contact* pc)
{assert(pc);//断言防止传入空指针//首先判断通讯录满每满if (0 == ChekCapacity(pc)){return;}printf("请输入联系人的名字>\n");scanf("%s", pc->data[pc->sz].name);//由于name是数组名这里就不要&符号了printf("请输入联系人的年龄>\n");scanf("%d", &(pc->data[pc->sz].age));printf("请输入联系人的性别>\n");scanf("%s", pc->data[pc->sz].sex);printf("请输入联系人的电话>\n");scanf("%s", pc->data[pc->sz].telepnumber);printf("请输入联系人的地址>\n");scanf("%s", pc->data[pc->sz].addr); //添加联系人成功,我们sz++pc->sz++;printf("添加联系人成功\n");}

测试一下:

先往通讯录里面放入三个联系人信息:

下一步增容:

增容成功,我们展现一下通讯录然后我们查找一下2号联系人:

功能正常。

 5.3显示所有联系人的信息

为了看一下我们添加联系人或者删除联系人的效果,我们这里就先写显示函数

用于我们只是显示通讯录信息,并不将参数内容进行修改所以参数最好使用const进行修饰,防止出错,这一步不理解的伙伴可以点击我的主页看一下我讲解const的博文。

这个函数我们只用循环打印我们data数组内容就行

void ShowContact(const Contact* pc)
{assert(pc);//断言一下防止传入空指针int i = 0;printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");for (i = 0; i < pc->sz; i++){printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n", pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].telepnumber,pc->data[i].addr);printf("————————————————————————————————————————————————————————————————————————————————————————\n");}printf("————————————————————————————————————————————————————————————————————————————————————————\n");

我们来看一下前两个函数执行的效果:

5.4删除指定联系人的信息 

首先,如果通讯录为空,我们就没有删除的东西

第二,要删除对应联系人的信息,实现思想是先找到对应联系人的名字匹配相同将后面的内容前移覆盖完成删除。

void DelCotact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}char name[DATAMAX] = { 0 };assert(pc);//断言,防止传入空指针printf("请输入要删除的人的名字:》\n");scanf("%s", name);//遍历找到要删除的人int i = 0;int del = 0;int flag = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){del = i;flag = 1;break;}}if (flag == 0){printf("找不到要删除的人,请检查名字是否输入正确\n");return;}//找到了,删除联系人for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人\n");
}

由于我们后面修改呀等等都会用到查找这个函数,所以我们将其封装为一个查找函数,那我们就可以改造代码如下:

int Findbyname(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//找不到
}
void DelCotact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}char name[DATAMAX] = { 0 };assert(pc);//断言,防止传入空指针printf("请输入要删除的人的名字:》\n");scanf("%s", name);//遍历找到要删除的人int i = 0;int del = 0;del = Findbyname(pc, name);if (del == -1){printf("找不到要删除的人,请检查名字是否输入正确\n");return;}//找到了,删除联系人for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人\n");
}

我们来看一下效果:

5.5查找指定联系人 

这里我们就实现一下通过名字查找,之所以单独写一个查找函数是因为在功能中,查找到过后还要显示出来。

看实现:

void SearchContact(Contact* pc)
{assert(pc);char name[DATAMAX] = { 0 };printf("请输入要查找的人的名字:》\n");scanf("%s", name);int pos = Findbyname(pc, name);if (pos == -1){printf("要查找的人不存在,请检查名字是否输入正确\n");}else{printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].telepnumber,pc->data[pos].addr);printf("————————————————————————————————————————————————————————————————————————————————————————\n");}
}

这里查找也可以根据其他的比如号码等,可以利用Switch来实现。看一下效果:

 5.6修改联系人的信息

通过名字来找到要修改信息的联系人,然后重新录入信息

void 	ModifyContact(Contact* pc)
{assert(pc);char name[DATAMAX] = { 0 };printf("请输入要修改人的名字:>\n");scanf("%s", name);int pos = Findbyname(pc, name);if (pos == -1){printf("要修改的人不存在,请检查名字是否输入正确\n");}else{printf("请输入要修改人的名字>\n");scanf("%s", pc->data[pos].name);//由于name是数组名这里就不要&符号了printf("请输入要修改人的年龄>\n");scanf("%d", &(pc->data[pos].age));printf("请输入要修改人的性别>\n");scanf("%s", pc->data[pos].sex);printf("请输入要修改人的电话>\n");scanf("%s", pc->data[pos].telepnumber);printf("请输入要修改人的地址>\n");scanf("%s", pc->data[pos].addr); \printf("修改成功\n");}
}

我们看一下效果:

 6.释放通讯录

由于我们的通讯录空间是malloc来的,所以在最后程序结束应该将空间释放,防止造成内存泄漏。

那我们就在退出选项后面增加一个销毁函数:

void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}

7.保存通讯录信息

在销毁通讯录前,通过文件读写的方式保存通讯录的信息

void Savecontact(Contact* pc)
{FILE* pf = fopen("contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}//写数据int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

看一下效果:

由于是二进制存储我们使用编译器来查看:

成功写入,我们搭配加载看一下是不是我们上一次添加的信息:

当通讯录再次启动就有我们上次写入的信息了。

8.源码及结语

这是一个综合C语言百分之五六十的知识的一个项目,大家可以配合我之前的文章进行理解,希望这篇文章对大家的期末有所帮助。下面附上源码,创作不易,如果可以大家可以点赞三连收藏,对于项目有问题欢迎一起交流。谢谢大家的关注。

contact.h

#pragma once
#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<stdlib.h>#define DATAMAX 100
#define CAPICITY 3
#define ADDC 2enum OPtion
{EXIT,//0ADD,//1DEL,//2SEARCH,MODIFY,SHOW,SORT};//类型的声明
typedef struct PeoInfo
{char name[20];int age;char sex[5];char telepnumber[12];char addr[30];} PeoInfo;//typedef struct Contact
//{
//	PeoInfo data[DATAMAX];
//	int sz;
//}Contact;
typedef struct Contact
{PeoInfo* data;//指向了存放数据的空间int sz;//记录的是当前有效元素的个数int  capacity;//记录当前存放数据空间的容量}Contact;//初始化函数
void Initcontact(Contact* pc);//函数声明
void AddContact(Contact* pc);//增加联系人函数
void ShowContact(const Contact* pc);//显示通讯录信息
void DelCotact(Contact* pc);//删除联系人信息
void SearchContact(Contact* pc);//查找联系人的信息
void 	ModifyContact(Contact* pc);//修改联系人的信息
void DestoryContact(Contact* pc);//销毁通讯录
void Savecontact(Contact* pc);//保存通讯录到文件

test.c

#include"contact.h"//通讯录空间不固定,大小1可以调整
// 默认放3个人的信息,不够,每次增加两个void menu()
{printf("----------------------------------\n");printf("|***0.Exit       1.ADD***********|\n");printf("|***2.DEL       3.SEARCH*********|\n");printf("|***4.MODIFY    5.SHOW***********|\n");printf("|***6.SORT       ****************|\n");printf("----------------------------------\n");}
void test()
{int  input = 0;Contact con;Initcontact(&con);do{menu();printf("请选择:》");scanf("%d", &input);switch (input){case ADD:AddContact(&con);break;case DEL:DelCotact(&con);break;case SEARCH:SearchContact(&con);break;case MODIFY:ModifyContact(&con);break;case SHOW:ShowContact(&con);break;case SORT:break;case EXIT:Savecontact(&con);DestoryContact(&con);printf("退出程序成功\n");break;default:printf("选择错误,请根据菜单选项进行功能选择,谢谢配合\n");break;}} while (input);
}int main()
{test();return 0;
}

contact.c

#include"contact.h"
int Findbyname(Contact* pc, char name[])
{assert(pc);int i = 0;for (i = 0; i < pc->sz; i++){if (strcmp(pc->data[i].name, name) == 0){return i;//找到了}}return -1;//找不到
}
int ChekCapacity(Contact* pc);//提前声明我们的检查增容函数
void LoadContact(Contact* pc)
{//首先用二进制读的方式打开文件FILE* pf = fopen("contact.dat", "rb");if (pf == NULL){//打开失败就不继续了perror("loadcontact");return;}//读文件PeoInfo tmp = { 0 };//创建一个联系人结构体来存储读到的信息while (fread(&tmp, sizeof(PeoInfo), 1, pf))//fred返回的是读到的个数,读完返回0{if (0 == ChekCapacity(pc))//这里因为要把读到的信息放到通讯录中,就要考虑增容return;//增容失败就不往下执行了//增容成功,将数据加载到通讯录pc->data[pc->sz] = tmp;pc->sz++;//加载一个联系人信息,sz++}//关闭文件fclose(pf);pf = NULL;}
void Initcontact(Contact* pc)
{assert(pc);pc->data = (PeoInfo*)malloc(CAPICITY * sizeof(PeoInfo));if (pc->data == NULL){perror("Initcontact");}pc->sz = 0;pc->capacity = CAPICITY;LoadContact(pc);
}
int ChekCapacity(Contact* pc)
{if (pc->sz == pc->capacity){PeoInfo* ptr = (PeoInfo*)realloc(pc->data, (pc->capacity + ADDC * sizeof(PeoInfo)));if (ptr == NULL){perror("ChekCapaticy");return  0;}else{pc->data = ptr;pc->capacity += ADDC;printf("增容成功\n");return 1;}}return 1;
}void AddContact(Contact* pc)
{assert(pc);//断言防止传入空指针//首先判断通讯录满每满if (0 == ChekCapacity(pc)){return;}printf("请输入联系人的名字>\n");scanf("%s", pc->data[pc->sz].name);//由于name是数组名这里就不要&符号了printf("请输入联系人的年龄>\n");scanf("%d", &(pc->data[pc->sz].age));printf("请输入联系人的性别>\n");scanf("%s", pc->data[pc->sz].sex);printf("请输入联系人的电话>\n");scanf("%s", pc->data[pc->sz].telepnumber);printf("请输入联系人的地址>\n");scanf("%s", pc->data[pc->sz].addr);//添加联系人成功,我们sz++pc->sz++;printf("添加联系人成功\n");}
void ShowContact(const Contact* pc)
{assert(pc);//断言一下防止传入空指针int i = 0;printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");printf("————————————————————————————————————————————————————————————————————————————————————————\n");for (i = 0; i < pc->sz; i++){printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",pc->data[i].name,pc->data[i].age,pc->data[i].sex,pc->data[i].telepnumber,pc->data[i].addr);printf("————————————————————————————————————————————————————————————————————————————————————————\n");}printf("————————————————————————————————————————————————————————————————————————————————————————\n");}void DelCotact(Contact* pc)
{if (pc->sz == 0){printf("通讯录为空,无法删除\n");return;}char name[DATAMAX] = { 0 };assert(pc);//断言,防止传入空指针printf("请输入要删除的人的名字:》\n");scanf("%s", name);//遍历找到要删除的人int i = 0;int del = 0;del = Findbyname(pc, name);if (del == -1){printf("找不到要删除的人,请检查名字是否输入正确\n");return;}//找到了,删除联系人for (i = del; i < pc->sz - 1; i++){pc->data[i] = pc->data[i + 1];}pc->sz--;printf("成功删除联系人\n");
}void SearchContact(Contact* pc)
{assert(pc);char name[DATAMAX] = { 0 };printf("请输入要查找的人的名字:》\n");scanf("%s", name);int pos = Findbyname(pc, name);if (pos == -1){printf("要查找的人不存在,请检查名字是否输入正确\n");}else{printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4s\t|%-5s\t|%-12s\t|%-30s|\n", "名字", "年龄", "性别", "电话", "地址");printf("————————————————————————————————————————————————————————————————————————————————————————\n");printf("|%-20s\t|%-4d\t|%-5s\t|%-12s\t|%-30s|\n",pc->data[pos].name,pc->data[pos].age,pc->data[pos].sex,pc->data[pos].telepnumber,pc->data[pos].addr);printf("————————————————————————————————————————————————————————————————————————————————————————\n");}
}void 	ModifyContact(Contact* pc)
{assert(pc);char name[DATAMAX] = { 0 };printf("请输入要修改人的名字:>\n");scanf("%s", name);int pos = Findbyname(pc, name);if (pos == -1){printf("要修改的人不存在,请检查名字是否输入正确\n");}else{printf("请输入要修改人的名字>\n");scanf("%s", pc->data[pos].name);//由于name是数组名这里就不要&符号了printf("请输入要修改人的年龄>\n");scanf("%d", &(pc->data[pos].age));printf("请输入要修改人的性别>\n");scanf("%s", pc->data[pos].sex);printf("请输入要修改人的电话>\n");scanf("%s", pc->data[pos].telepnumber);printf("请输入要修改人的地址>\n");scanf("%s", pc->data[pos].addr); \printf("修改成功\n");}
}void DestoryContact(Contact* pc)
{free(pc->data);pc->data = NULL;pc->capacity = 0;pc->sz = 0;
}void Savecontact(Contact* pc)
{FILE* pf = fopen("contact.dat", "wb");if (pf == NULL){perror("SaveContact");return;}//写数据int i = 0;for (i = 0; i < pc->sz; i++){fwrite(pc->data + i, sizeof(PeoInfo), 1, pf);}//关闭文件fclose(pf);pf = NULL;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/472117.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java springmvc+mybatis酒店信息管理系统设计和实现

基于Java springmvcmybatis酒店信息管理系统设计和实现 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 作者主页 超级帅帅吴 Java毕设项目精品实战案例《1000套》 欢迎点赞 收藏 ⭐留言 文末获取…

【复现】cellinx摄像设备 未授权漏洞_50

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 cellinx是一家韩国的摄像设备 二 .漏洞影响 通过未授权访问可以创建用户进入后台&#xff0c;可能造成系统功能破坏。 三.漏洞复…

枚举,#define,C中程序内存区域划分

目录 一、枚举 1.1枚举类型的声明 1.2枚举类型的优点 1.3枚举类型的使用 二、#define定义常量 三、C中程序内存区域划分 一、枚举 1.1枚举类型的声明 枚举顾名思义就是⼀⼀列举。 把可能的取值⼀⼀列举。 比如我们现实生活中&#xff1a; ⼀周的星期⼀到星期日是有限…

数值类型的运算方式总结

提纲1&#xff1a;常见的位运算使用场景 提纲2&#xff1a;整数类型运算时的类型溢出问题&#xff0c;产生原因以及解决办法 提纲3&#xff1a;浮点类型运算时的精度丢失问题&#xff0c;产生原因以及解决办法 数值类型&#xff08;6种&#xff09;分为&#xff1a; 整型&…

高校疫情防控系统的全栈开发实战

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

英文单词-计算: calculate、count、compute、reckon

英文单词-计算: calculate、count、compute、reckon count 数数; 计算总数; 重要; 包括在内; 正式认可; 认为; 被视作; compute 计算&#xff0c;估算; calculate 计算; 估算; 估计; 预料; reckon 测算&#xff0c;估计; 认为; 计算; 评定&#xff0c;断定; 这四个单词 “c…

Mock.js

在开发后端的应用中&#xff0c;我们使用postman来测试接口&#xff0c;观察和验证前后端之间的数据传递是否正常。 在开发前端的应用中&#xff0c;我们使用Mock.js来模拟后端服务&#xff0c;以便进行前端业务逻辑的开发和测试。 一般情况下&#xff0c;个人开发或者小团队开…

laravel_进程门面_简单介绍

文章目录 Facade是什么&#xff1f;Facade能干什么Facade有哪些方法&#xff1f;怎么使用Facade呢&#xff1f;详细的代码解释Symfony Process是什么&#xff1f;介绍Symfony总结 Facade是什么&#xff1f; 在 Laravel 框架中&#xff0c;Facade 是一种设计模式。 它提供了一…

杨中科 .netcore 依赖注入

1.概念 概念 生活中的“控制反转”:自己发电和用电网的电。 依赖注入(Dependency Injection&#xff0c;Dl)是控制反转:(Inversion of Control&#xff0c;l0c)思想的实现方式。 依赖注入简化模块的组装过程&#xff0c;降低模块之间的耦合度 自己发电的代码 var connSetti…

炬芯ATS2819 soundbar音响系统开发完全手册

加我微信hezkz17,可申请加入数字音频系统研究开发交流答疑群,赠送音频项目核心开发资料 ATS2819音响系统开发完全手册 1 硬件原理实现 图1 硬件原理框图 2 SOC ATS2819介绍 3 E800 板子项目实物…

基于BP算法的SAR成像matlab仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 4.1 BP算法的基本原理 4.2 BP算法的优点与局限性 5.完整工程文件 1.课题概述 基于BP算法的SAR成像。合成孔径雷达&#xff08;SAR&#xff09;是一种高分辨率的雷达系统&#xff0c;能够在各种天气和光…

Tcl 过程

一个Tcl过程就是Tcl脚本定义的一个命令。可以使用proc命令定义新的过程。Tcl还提供了处理变量作用域的特殊命令&#xff0c;这些命令允许使用引用而非值传递参数&#xff0c;并能把新的Tcl控制结构实现为过程。 一、proc与return 过程由proc命令创建, 其中参数{a b} 中的大括…