顺序表应用——通讯录

在本篇之前的顺序表专题我们已经学习的顺序表的实现,了解了如何实现顺序表的插入和删除等功能,那么在本篇当中就要学习基于顺序表来实现通讯录,在通讯录当中能实现联系人的增、删、查改等功能,接下来就让我们一起来实现通讯录吧!
 


 1.实现通讯录前的分析

在实现通讯录的代码前我们要先思考在通讯录项目中能实现什么样的功能
(1)至少能够存储100个人的通讯信息
(2)能够保存用户信息:名字、性别、年龄、电话、地址等
(3)增加联系人信息
(4)删除指定联系人
(5)查找制定联系人
(6)修改指定联系人
(7)显示联系人信息

同时由于在之前的顺序表中使用的是动态顺序表,所以在实现通讯录项目中也基于的是动态顺序表

以下是该通讯录项目的程序文件设置以及各文件中所实现的内容

 

2.通讯录的实现 

2.1 联系人信息的设置以及顺序表内要做出的更改

 由于顺序表的底层就是数组,所以我们就是要利用数组来实现如以下所示的结构

在通讯录中由于我们要存储的是多个联系人的信息,因此要定义一个结构体来存储联系人的信息
以下定义结构体struct PersonIfon来存储联系人的信息,并且使用typedef将该结构体重命名为Persondef
并且在PersonIfon中的每个数组的大小用#define来定义

#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADRESS 50typedef struct PersonIfon//联系人信息
{char name[MAX_NAME];//姓名char Gender[MAX_GENDER];//性别int age;//年龄char Tele[MAX_TELE];//电话char Adress[MAX_ADRESS];//地址}PersonIfon;

同时由于要通讯录所以之前顺序表的Sqelist.h的数组类型也要更改,由用来的整型改变为PersonIfon,要实现该改变就需要在Seqlist.h内代码的头加上#define“contact.h”

这时Seqlist.h就变为以下形式

#pragma once
#define  _CRT_SECURE_NO_WARNINGS 1
#include"contact.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>typedef struct PersonIfon SLDataType;
typedef struct Seqlist
{SLDataType* arr;int size;//有效的数据个数int capacity;//空间大小}SL;//将struct Seqlist重命名为SL

在之前的顺序表的结构体struct Seqlist被重命名为SL,但现在我们要实现的是通讯录这时这个名字就不太合适与直观,那该如何来在contact.h文件内对struct Seqlist进行重命名呢?
这时你可能想到是在contact.h内加上预处理指令#define“Seqlist.h”,
但这样就存在问题了,在之前的操作中我们已经在Seqlaist.h文件内包含了contact.h,如果在这再在contact.h内包含Seqlist.h就会存在头文件相互包含的问题,这时程序就会崩溃

所以正确的解决方法是什么呢?
其实这时只需要在contact.h中先声明以下struct Seqlist就可以对该结构体进行重命名了

struct Seqlist;
typedef struct Seqlist contact;

2.2  通讯录的初始化以及销毁


在以上完成联系人结构体的定义以及对顺序表内数组类型的更改,接下来就可以来实现通讯录初始化和销毁的函数了

在此先在contact.h内声明初始化函数以及销毁函数,由于在此要对通讯录内容进行更改,所以要进行传址调用,两个函数的参数都是结构体指针

void ContactInit(contact* con);//初始化通讯录
void ContactDestory(contact* con);//销毁通讯录

声明完之后就是在contact.c内实现以上两个函数,在此通讯录的初始化以及销毁内就可以直接调用之前顺序表的初始化以及销毁函数了

void ContactInit(contact* con)//通讯录初始化
{SLInit(con);
}
void ContactDestory(contact* con)//销毁通讯录
{SLDestory(con);
}

2.3通讯录的展示 

通讯录的展示就是将通讯录的信息都打印出来,实质就是要遍历一般数组
在此在printf中在占位符中的%后加入的最小宽度限制来让打印出的通讯录更有顺序

void ContactShow(contact* con)//展示通讯录
{printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < con->size; i++){printf("%-10s %-4s %-4d %15s %-20s\n",con->arr[i].name,con->arr[i].Gender,con->arr[i].age,con->arr[i].Tele,con->arr[i].Adress);}
}

2.4通讯录各功能实现

在以上完成了通讯录的初始化和销毁接下来我们就来实现通讯录增、删、查、改的功能了

2.4.1 通讯录内添加联系人 

在此要实现通讯录中联系人的增加先在contact.h内对增加联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactAdd(contact* con);//通讯录内添加联系人

接下来就是在contact.c内完成添加联系人的函数
在此先创建一个结构体PersonIfon ifon,并且使用scanf来读取用户输入的此联系人的各信息存储在结构体ifon内,再调用顺序表中的插入函数将该结构体ifon插入到数组内,在此使用的是尾插函数,也可以使用其他插入方法

void ContactAdd(contact* con)//在通讯录内添加联系人
{PersonIfon ifon;printf("请输入联系人姓名:\n");scanf("%s", &ifon.name);printf("请输入联系人性别:\n");scanf("%s", &ifon.Gender);printf("请输入联系人年龄:\n");scanf("%d", &ifon.age);printf("请输入联系人电话:\n");scanf("%s", &ifon.Tele);printf("请输入联系人地址:\n");scanf("%s", &ifon.Adress);SLPushBack(con, ifon);
}

2.4.2 通讯录内删除联系人

在此要实现通讯录中联系人的删除先在contact.h内对删除联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactDel(contact* con);//通讯录内删除联系人

在声明完函数之后就是对该函数的实现,但在删除通讯录内的联系人要通讯录中存在要删除的联系人才能删除,所以在函数内还要先判断,但之后通讯录的其他功能可能还要用到查找联系人是否存在

所以可以直接在创建一个判断相关联系人是否存在的函数,在此根据的是名字来查找联系人

存在该联系人就返回相应的数组下标,不存在就返回-1

int FindbyName(contact* con, char* name)
{for (int i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name)==0){return i;}}return -1;
}

接下来就是在contact.c内完成删除联系人的函数
在此函数内先定义一个char类型的数组name,大小为MAX_NAME。用scanf将用户输入的联系人姓名存放在该数组内,之后再将指针con与name作为FindbyName的参数,通过FindbyName函数的返回值来得到要删除的联系人是否存在。若返回值小于0则说明该联系人不存在,之后就直接退出函数ContactDel,否则就调用顺序表中的任意位置的删除函数SLErase,这时tmp就是要删除的数组下标

void ContactDel(contact* con)//通讯录内删除联系人
{char name[MAX_NAME];printf("请输入要删除的联系人的姓名\n");scanf("%s", name);int tmp = FindbyName(con, name);if (tmp < 0){printf("该联系人不存在,删除失败\n");return;}SLErase(con, tmp);printf("删除成功\n");}

 2.4.3 通讯录内修改联系人

在此要实现通讯录中联系人的修改先在contact.h内对修改联系人函数进行声明,由于在此要对通讯录内容进行更改,所以要进行传址调用,函数的参数是结构体指针

void ContactModify(contact* con);//通讯录内修改联系人

 接下来就是在contact.c内完成修改联系人的函数
在该函数内和删除联系人函数一样也是先在此函数内先定义一个char类型的数组name,大小为MAX_NAME。用scanf将用户输入的联系人姓名存放在该数组内,之后再将指针con与name作为FindbyName的参数,通过FindbyName函数的返回值来得到要修改的联系人是否存在。若返回值小于0则说明该联系人不存在,之后就直接退出函数ContactDel。否则就使用scanf将用户输入的信息存放到原来联系人的数组位置

void ContactModify(contact* con)//修改联系人信息
{char name[MAX_NAME];printf("请输入要修改的联系人的姓名\n");scanf("%s", name);int tmp = FindbyName(con, name);if (tmp < 0){printf("该联系人不存在,修改失败\n");return;}//直接修改printf("请输入新的联系人姓名:\n");scanf("%s", con->arr[tmp].name);printf("请输入新的联系人性别:\n");scanf("%s", con->arr[tmp].Gender);printf("请输入新的联系人年龄:\n");scanf("%d", &con->arr[tmp].age);printf("请输入新的联系人电话:\n");scanf("%s", con->arr[tmp].Tele);printf("请输入新的联系人地址:\n");scanf("%s", con->arr[tmp].Adress);printf("修改成功!\n");}

 2.4.4 通讯录内查找联系人

 在此要实现通讯录中联系人的修改先在contact.h内对修改联系人函数进行声明,在此虽然查找联系人未对通讯录内数据进行修改,但在此还是将结构体作为函数的参数,原因通讯录其他函数都是传地址在此也保持一致性

void ContactFind(contact* con);//在通讯录内查找联系人

  接下来就是在contact.c内完成查找联系人的函数

在该函数内也是先定义一个char类型的数组name,再通过scanf函数将用户输入的字符串存储到数组内,在此并定义一个变量flag=-1再通过for循环遍历数组中的各个元素中的name是否和数组name相同相同就将flag赋值为1,相同就打印该元素的联系人信息,当遍历完时flag如果等于-1就打印查找不到联系人

void ContactFind(contact* con)//查找联系人
{char name[MAX_NAME];printf("请输入要查找的联系人的姓名\n");scanf("%s", name);int flag = -1;for (int i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name) == 0){flag = 1;printf("查找成功!\n");printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-4s %-4d %15s %-20s\n",con->arr[i].name,con->arr[i].Gender,con->arr[i].age,con->arr[i].Tele,con->arr[i].Adress);}}if (flag == -1){printf("你所要查找的联系人不存在!\n");}}

 

3.通讯录test.c文件

在以上我们已经实现了通讯录各种功能,现在就需要在test.c内将这些设计好的功能给拼装起来,让程序能在运行窗口通过输入不同的数就可以实现通讯录的各功能
 

注:在test.c的开头要加上#include"SeqList.h"和#include"contact.h"

先在test.c内先创建main函数,同时要实现对通讯录的多次操作就需要用到循环,在此用的是do...while循环,在循环内在创建一个switch语句来实现用户输入不同的信息就进入不同的函功能。在switch语句内的case后的常量都使用枚举所定义的,这样会使得代码的可读性更高、同时shitch语句的case语句排序也可以是不按顺序来的。在不同的case语句内就调用不同的通讯录功能函数
 

在进入循环先初始化顺序表,退出循环就销毁顺序表 

#include"SeqList.h"
#include"contact.h"void menu()
{printf("**************************************\n");printf("******1.添加联系人  2.删除联系人******\n");printf("******3.查找联系人  4.修改联系人******\n");printf("******5.展示通讯录  0.退出程序  ******\n");printf("**************************************\n");}enum option
{ADD=1,DEL=2,FIND=3,MODIFY=4,SHOW=5};int main()
{int input = 0;contact con;ContactInit(&con);do{menu();printf("请选择操作\n");scanf("%d", &input);switch (input){case ADD:ContactAdd(&con);break;case DEL:ContactDel(&con);break;case FIND:ContactFind(&con);break;case MODIFY:ContactModify(&con);break;case SHOW:ContactShow(&con);break;default:printf("选择操作错误,请输入1~5内的数\n");break;}} while(input);//当输入的值为0时,input值也就也0,在此判断部分input就为假就会退出循环ContactDestory(&con);return 0;
}

 

4. 通讯录读取历史数据和保存数据

在之前已经实现了通讯录的各功能的数据只能在程序运行窗口打开的时候进行通讯录的增、删、查、改等功能。在关闭窗口后对通讯录进行的各项操作都不会保存,那么要怎么样才能让我们设计的通讯录在每次开始之前都读取之前的信息,在结束后都保存通讯录的信息呢?

在之前文件操作章节中讲解了如何将程序数据输出到文件中,将文件数据输入到程序当中,所以在通讯录中我们就可以用到文件操作的相关函数来实现通讯录数据的保存与读取。

 

4.1读取历史数据

要读取历史数据就要在通讯录每次初始化之后就输入文件的信息到所创建的通讯录中,也就是将输入到数组当中。

在此先在我们创建的程序的文件夹中创建一个con.txt文本,再使用fopen以读的方式打开文件,再创建一个PersonIfon ifon的变量,之后在使用到fread以二进制的形式输入文件的信息到创建的ifon中,再将ifon尾插到数组当中。

void ContactRead(contact* con)//从文件中读取历史数据
{FILE* pf = fopen("con.txt", "rb");if (pf == NULL){perror("fopen");return;}PersonIfon ifon;while (fread(&ifon, sizeof(PersonIfon), 1, pf)){SLPushBack(con, ifon);}printf("成功读取历史数据到通讯录中\n");
}

 

在通讯录初始化函数中调用SLInit函数后调用COntactRead就可以实现历史数据的读取

void ContactInit(contact* con)//通讯录初始化
{SLInit(con);ContactRead(con);
}

 

4.2 保存数据

要实现通讯录每次在退出程序后都能将数据保留,这就需要在每次销毁通讯录前将通讯录内的数据,也就是数组的所有元素都输出到con.txt文件内。

要把数组的所有元素都输出到con.txt文件内就需要先以写的方式打开文件,后在循环的使用fwrite将数组的数据以二进制的形式输出到文件当中

void ContactWrite(contact* con)//将通讯录数据读入文件中
{FILE* pf = fopen("con.txt", "wb");if (pf == NULL){perror("fopen\n");return;}for (int i = 0; i < con->size; i++){fwrite(con->arr+i, sizeof(PersonIfon), 1, pf);}printf("通讯录数据保存成功\n");
}

 

在通讯录销毁函数中调用SLDestory函数前调用COntactWrite就可以实现数据输出到文件当中,也就将数据保留了下来

void ContactDestory(contact* con)//销毁通讯录
{ContactWrite(con);SLDestory(con);
}

 


通讯录完整代码 
 

注:在Seqlist.h和Seqlist.c内的查找和打印顺序表与以上代码不兼容,运行时会使得程序崩溃,所以将这些部分注释掉 

contact.h 

#pragma once
#define MAX_NAME 20
#define MAX_GENDER 10
#define MAX_TELE 20
#define MAX_ADRESS 50typedef struct PersonIfon//联系人信息
{char name[MAX_NAME];//姓名char Gender[MAX_GENDER];//性别int age;//年龄char Tele[MAX_TELE];//电话char Adress[MAX_ADRESS];//地址}PersonIfon;struct Seqlist;
typedef struct Seqlist contact;void ContactInit(contact* con);//初始化通讯录
void ContactDestory(contact* con);//销毁通讯录
void ContactAdd(contact* con);//通讯录内添加联系人
void ContactDel(contact* con);//通讯录内删除联系人
void ContactModify(contact* con);//通讯录内修改联系人
void ContactFind(contact* con);//在通讯录内查找联系人
void ContactShow(contact* con);//展示通讯录void ContactRead(contact* con);//从文件中读取历史数据
void ContactWrite(contact* con);//将通讯录数据读入文件中

 

Seqlist.h

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>typedef struct PersonIfon SLDataType;
typedef struct Seqlist
{SLDataType* arr;int size;//有效的数据个数int capacity;//空间大小}SL;//将struct Seqlist重命名为SLvoid SLInit(SL* ps);//初始化
void SLDestory(SL* ps);//销毁void SLCheckCapacity(SL* ps);//检查空间是否足够
//void SLPrint(SL ps);//打印顺序表void SLPushBack(SL* ps, SLDataType x);//尾插
void SLPushPront(SL* ps, SLDataType x);//头插void SLPopBack(SL* ps);//尾删
void SLPopPront(SL* ps);//头删void SLInsert(SL* ps, int pos, SLDataType x);//任意位置插入
void SLErase(SL* ps, int pos);//任意位置删除//int SLFind(SL* ps, SLDataType x);//查找

 

 

Seqlist.c 

#include"SeqList.h"void SLInit(SL* ps)//顺序表初始化
{ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLDestory(SL* ps)//顺序表销毁
{if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->size = ps->capacity = 0;
}void SLCheckCapacity(SL* ps)//检查空间是否足够,不足时增大空间大小
{if (ps->size == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity * sizeof(SLDataType));if (tmp == NULL){perror("realloc");exit(1);}ps->arr = tmp;ps->capacity = newcapacity;}
}//void SLPrint(SL ps)//打印
//{
//	int i = 0;
//	for (i; i < ps.size; i++)
//	{
//		printf("%d ", ps.arr[i]);
//	}
//	printf("\n");
//}void SLPushBack(SL* ps, SLDataType x)//尾插
{assert(ps);SLCheckCapacity(ps);ps->arr[ps->size++] = x;
}void SLPushPront(SL* ps, SLDataType x)//头插
{assert(ps);SLCheckCapacity(ps);for (int i = ps->size; i > 0; i--){ps->arr[i] = ps->arr[i - 1];   //pa->arr[1]=pa->arr[0]}ps->arr[0] = x;ps->size++;
}void SLPopBack(SL* ps)//尾删
{assert(ps);assert(ps->size);ps->size--;
}void SLPopPront(SL* ps)//头删
{assert(ps);assert(ps->size);for (int i = 0; i < ps->size - 1; i++){ps->arr[i] = ps->arr[i + 1];}ps->size--;
}void SLInsert(SL* ps, int pos, SLDataType x)//任意位置插入
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);for (int i = ps->size; i > pos; i--){ps->arr[i] = ps->arr[i - 1];//结束条件ps->arr[pos+1] = ps->arr[pos]}ps->arr[pos] = x;ps->size++;}void SLErase(SL* ps, int pos)//任意位置删除
{assert(ps);assert(pos >= 0 && pos < ps->size);for (int i = pos; i <= ps->size - 2; i++){ps->arr[i] = ps->arr[i + 1];//结束条件ps->arr[ps->size-2] = ps->arr[ps->size-1]}--ps->size;
}//int SLFind(SL* ps, SLDataType x)//查找
//{
//	assert(ps);
//	for (int i = 0; i < ps->size; i++)
//	{
//		if (ps->arr[i] == x)
//		{
//			return i;
//		}
//	}
//	return -1;
//
//}

 

contact.c 

#pragma once
#include "contact.h"
#include"SeqList.h"void ContactRead(contact* con)//从文件中读取历史数据
{FILE* pf = fopen("con.txt", "rb");if (pf == NULL){perror("fopen");return;}PersonIfon ifon;while (fread(&ifon, sizeof(PersonIfon), 1, pf)){SLPushBack(con, ifon);}printf("成功读取历史数据到通讯录中\n");
}void ContactInit(contact* con)//通讯录初始化
{SLInit(con);ContactRead(con);}void ContactWrite(contact* con)//将通讯录数据读入文件中
{FILE* pf = fopen("con.txt", "wb");if (pf == NULL){perror("fopen\n");return;}for (int i = 0; i < con->size; i++){fwrite(con->arr+i, sizeof(PersonIfon), 1, pf);}printf("通讯录数据保存成功\n");
}void ContactDestory(contact* con)//销毁通讯录
{ContactWrite(con);SLDestory(con);}void ContactAdd(contact* con)//在通讯录内添加联系人
{PersonIfon ifon;printf("请输入联系人姓名:\n");scanf("%s", &ifon.name);printf("请输入联系人性别:\n");scanf("%s", &ifon.Gender);printf("请输入联系人年龄:\n");scanf("%d", &ifon.age);printf("请输入联系人电话:\n");scanf("%s", &ifon.Tele);printf("请输入联系人地址:\n");scanf("%s", &ifon.Adress);SLPushBack(con, ifon);}int FindbyName(contact* con, char* name)
{for (int i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name)==0){return i;}}return -1;
}void ContactDel(contact* con)//通讯录内删除联系人
{char name[MAX_NAME];printf("请输入要删除的联系人的姓名\n");scanf("%s", name);int tmp = FindbyName(con, name);if (tmp < 0){printf("该联系人不存在,删除失败\n");return;}SLErase(con, tmp);printf("删除成功\n");}void ContactModify(contact* con)//修改联系人信息
{char name[MAX_NAME];printf("请输入要修改的联系人的姓名\n");scanf("%s", name);int tmp = FindbyName(con, name);if (tmp < 0){printf("该联系人不存在,修改失败\n");return;}printf("请输入新的联系人姓名:\n");scanf("%s", con->arr[tmp].name);printf("请输入新的联系人性别:\n");scanf("%s", con->arr[tmp].Gender);printf("请输入新的联系人年龄:\n");scanf("%d", &con->arr[tmp].age);printf("请输入新的联系人电话:\n");scanf("%s", con->arr[tmp].Tele);printf("请输入新的联系人地址:\n");scanf("%s", con->arr[tmp].Adress);printf("修改成功!\n");}void ContactFind(contact* con)//查找联系人
{char name[MAX_NAME];printf("请输入要查找的联系人的姓名\n");scanf("%s", name);int flag = -1;for (int i = 0; i < con->size; i++){if (strcmp(con->arr[i].name, name) == 0){flag = 1;printf("查找成功!\n");printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");printf("%-10s %-4s %-4d %15s %-20s\n",con->arr[i].name,con->arr[i].Gender,con->arr[i].age,con->arr[i].Tele,con->arr[i].Adress);}}if (flag == -1){printf("你所要查找的联系人不存在!\n");}}void ContactShow(contact* con)//展示通讯录
{printf("%-10s %-4s %-4s %15s %-20s\n", "姓名", "性别", "年龄", "电话", "地址");for (int i = 0; i < con->size; i++){printf("%-10s %-4s %-4d %15s %-20s\n",con->arr[i].name,con->arr[i].Gender,con->arr[i].age,con->arr[i].Tele,con->arr[i].Adress);}
}

 

 test.c

#include"SeqList.h"
#include"contact.h"void menu()
{printf("**************************************\n");printf("******1.添加联系人  2.删除联系人******\n");printf("******3.查找联系人  4.修改联系人******\n");printf("******5.展示通讯录  0.退出程序  ******\n");printf("**************************************\n");}enum option
{ADD=1,DEL=2,FIND=3,MODIFY=4,SHOW=5};int main()
{int input = 0;contact con;ContactInit(&con);do{menu();printf("请选择操作\n");scanf("%d", &input);switch (input){case ADD:ContactAdd(&con);break;case DEL:ContactDel(&con);break;case FIND:ContactFind(&con);break;case MODIFY:ContactModify(&con);break;case SHOW:ContactShow(&con);break;default:printf("选择操作错误,请输入1~5内的数\n");break;}} while(input);ContactDestory(&con);return 0;
}

通讯录实现效果 
 

基于顺序表实现通讯录

 

以上就是本篇的所有内容了,希望能得到你的点赞与收藏,感谢支持!!!

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

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

相关文章

grpc学习golang版( 五、多proto文件示例 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件2.1 公共proto文件2.2 语音唤醒proto文…

基于局域网下的服务器连接、文件传输以及内网穿透教程 | 服务器连接ssh | 服务器文件传输scp | 内网穿透frp | 研究生入学必备 | 深度学习必备

&#x1f64b;大家好&#xff01;我是毛毛张! &#x1f308;个人首页&#xff1a; 神马都会亿点点的毛毛张 &#x1f4cc;本篇博客分享的是基于局域网下的服务器连接&#x1f517;、文件传输以及内网穿透教程&#xff0c;内容非常完备✨&#xff0c;涵盖了在服务器上做深度学…

树莓派3B读写EEPROM芯片AT24C256

AT24C256是一个Atmel公司的EEPROM存储芯片&#xff0c;容量是256K个bit&#xff08;也就是32K字节&#xff09;&#xff0c;I2C接口&#xff0c;而树莓派正好有I2C接口&#xff0c;如下图蓝框中的4个IO口&#xff0c; 把AT24C256和这4个口接在一起&#xff0c;这样硬件就准备好…

Django 页面展示模型创建表的数据

1&#xff0c;添加视图函数 Test/app8/urls.py from django.shortcuts import render from .models import Userdef create_user(request):if request.method POST:username request.POST.get(username)email request.POST.get(email)# ... 获取其他字段的值# 创建用户实例…

【Python学习篇】Python实验小练习——异常处理(十三)

个人名片&#xff1a; &#x1f393;作者简介&#xff1a;嵌入式领域优质创作者&#x1f310;个人主页&#xff1a;妄北y &#x1f4de;个人QQ&#xff1a;2061314755 &#x1f48c;个人邮箱&#xff1a;[mailto:2061314755qq.com] &#x1f4f1;个人微信&#xff1a;Vir2025WB…

【教程】5分钟直接了解随机森林模型

本文来自《老饼讲解-BP神经网络》https://www.bbbdata.com/ 目录 一、什么是随机森林模型1.1.随机森林模型介绍1.2.为什么随机森林要用多棵决策树 二、怎么训练一个随机森林模型2.1.训练一个随机森林模型 随机森林模型是机器学习中常用的模型之一&#xff0c;它是决策树模型的一…

Node.js全栈指南:静态资源服务器

上一章【认识 MIME 和 HTTP】。 我们认识和了解了 MIME 的概念和作用&#xff0c;也简单地学习了通过浏览器控制台查看请求和返回的用法。 通过对不同的 HTML、CSS、JS 文件进行判断&#xff0c;设置不同的 MIME 值&#xff0c;得以让我们的浏览器正正确地接收和显示不同的文…

八爪鱼现金流-031,宽带到期记一笔负债

到期了&#xff0c;新弄的网络&#xff0c;记录一下负债包。 八爪鱼现金流 八爪鱼

英英词典(汇编实验)

功能要求&#xff1a; 1.单词及其英文解释的录入、修改和删除 (1 ) 录入新单词&#xff0c;把它插入到相应的位置(按词典顺序)&#xff0c;其后跟英文解释、同义词、反义词&#xff1b;&#xff08;此功能要求在文件中完成&#xff0c;其它功能可以将单词放在数据段中&#xf…

数据库原理之数据库基本概念

目录 前言 基本概念 数据库完整性 前言 今天我们来看看数据库的基本概念&#xff0c;帮助大家对数据库有一点点最基本的了解 基本概念 4个基本概念 数据data&#xff1a;描述事物的符号&#xff0c;数据库中存储的基本对象。 数据库Database&#xff1a;长期存储在计算机…

山东大学多核并行2024年回忆版

2024.6.13回忆版 矩阵向量乘不可整除代码 集合通信与点对点通信的区别 块划分、循环划分、循环块划分&#xff08;14个向量&#xff0c;4个进程&#xff09; 按行访问还是按列访问快 SISD系统问题 循环依赖问题 问题&#xff1a;为什么不能对这个循环并行化&#xff0…

Python逻辑控制语句 之 综合案例

需求&#xff1a; 1. 提示⽤户输⼊登录系统的⽤户名和密码 2. 校验⽤户名和密码是否正确(正确的⽤户名:admin、密码:123456) 3. 如果⽤户名和密码都正确&#xff0c;打印“登录成功!”&#xff0c;并结束程序 4. 如果⽤户名或密码错误&#xff0c;打印“⽤户名或密码错误!”…

Django 对模型创建的两表插入数据

1&#xff0c;添加模型 Test/app8/models.py from django.db import modelsclass User(models.Model):username models.CharField(max_length50, uniqueTrue)email models.EmailField(uniqueTrue)password models.CharField(max_length128) # 使用哈希存储密码first_name …

DM 的断点续传测试

作者&#xff1a; 大鱼海棠 原文来源&#xff1a; https://tidb.net/blog/4540ae34 一、概述 DM有all、full、incremental三种数据迁移同步方式&#xff08;task-mode&#xff09;&#xff0c;在all同步模式下&#xff0c;因一些特殊情况&#xff0c;需要变更上游MySQL的数…

LDO产品的基础知识解析

低压降稳压器 (LDO)是一种用于调节较高电压输入产生的输出电压的简单方法。在大多数情况下&#xff0c;低压降稳压器都易于设计和使用。然而&#xff0c;如今的现代应用都包括各种各样的模拟和数字系统&#xff0c;而有些系统和工作条件将决定哪种LDO最适合相关电路&#xff0c…

springboot的特点是什么?

Spring Boot是一个基于Spring框架的开源项目&#xff0c;它旨在简化Spring应用的初始搭建和开发过程。以下是Spring Boot的一些主要特点&#xff1a; 快速开发&#xff1a; Spring Boot提供了许多默认配置&#xff0c;使得开发者可以更快地开始开发应用程序&#xff0c;而无需…

秋招突击——6/28、6.29——复习{数位DP——度的数量}——新作{}

文章目录 引言复习数位DP——度的数量个人实现参考实现 总结 引言 头一次产生了那么强烈的动摇&#xff0c;对于未来没有任何的感觉的&#xff0c;不知道将会往哪里走&#xff0c;不知道怎么办。可能还是因为实习吧&#xff0c;再加上最近复习也没有什么进展&#xff0c;并不知…

如何借助 LLM 设计和实现任务型对话 Agent

1 引言 在人工智能的快速发展中&#xff0c;任务型对话 Agent 正成为提升用户体验和工作效率的关键技术。这类系统通过自然语言交互&#xff0c;专注于高效执行特定任务&#xff0c;如预订酒店或查询天气。尽管市场上的开源框架如 Rasa 和 Microsoft Bot Framework 在对话理解…

揭秘多年免费听音乐、直播、影视的自用方案:手机、电视、电脑多平台0成本实现媒体自由(内含相关资源)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 多媒体自由 📒🎧 音乐资源📱安卓平台🍎 苹果平台💻 PC平台🎥 影视资源📱 安卓平台🍎 苹果平台📺 电视盒子💻 PC平台📥 电影下载📺 直播资源📱 手机平台💻 PC平台📺 电视盒子⚓️ 相关链接 ⚓️�…