电子词典项目
目录
目录
头文件:dict.h:
源文件:dict.c:
服务器测试文件:serDict.c:
客户端测试文件:cliDict.c:
头文件:dict.h:
#ifndef __DICT_H__
#define __DICT_H__
#include<myhead.h>
#include<sqlite3.h>#define SERIP "192.168.114.73"
#define PORT 8888#define ERR_MSG(msg) do{\printf("%d: ",__LINE__);\perror(msg);\
}while(0);/*服务器使用 */
//词典数据库的初始化和导入
int dict_init(sqlite3 *db);//TCP服务器搭建函数
int TCP_ser_set(struct sockaddr_in* psin);//回收子进程函数
void handler(int signum);//子进程中的操作
void child_operate(int newfd, sqlite3 *db);
/*服务器使用 *//*客户端使用 */
//TCP客户端搭建函数
int TCP_cli_set();//客户端中的操作
void cli_operate(int cfd);/*客户端使用 */
#endif
源文件:dict.c:
#include<myhead.h>
#include<sqlite3.h>
#include "dict.h"int do_create(sqlite3 *db);
int do_insert(sqlite3 *db, char * English, char *Chinese);
int msg_get(FILE *fp, char*pEng, char *pChin);
int do_init(sqlite3 *db);
int usrname_not_reuse(sqlite3 *db, const char *usrname, const char *tablename);int dict_init(sqlite3 *db)
{//初始化数据库中词典数据表do_init(db);printf("数据库初始化成功\n");//打开文件FILE *fp;char English[32] = "";char Chinese[64] = "";if(NULL == (fp=fopen("./dict.txt","r"))){printf("%d:",__LINE__);perror("fopen error");return -1;}//创建表格do_create(db);printf("词典数据导入中\n...\n");while(1){//从dict.txt中读取一行的数据bzero(English, sizeof(English));bzero(Chinese, sizeof(Chinese));msg_get(fp, English, Chinese);//将English和Chinese写入表格中do_insert(db, English, Chinese);//printf("%s\t%s\n",English, Chinese);if(feof(fp)){printf("导入成功\n");break;}}//关闭文件fclose(fp);return 0;
}int msg_get(FILE *fp, char* pEng, char *pChin){char tmp = 0;int i = 0;while((tmp = fgetc(fp))!=' '){pEng[i] = tmp;i++;if(feof(fp)){return 0;}}i = 0;while(fgetc(fp)==' ');fseek(fp,-1,SEEK_CUR);while((tmp = fgetc(fp))!='\n'){pChin[i] = tmp;i++;if(feof(fp)){pChin[i-1] = 0;break;}}return 0;
}int do_create(sqlite3 *db){if(db == NULL){printf("数据库不存在\n");return -1;}//创建词典数据表char sql[128] = "create table if not exists dict(ENGLISH char, TRANSLATION char);";char *errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }//创建已注册用户数据表bzero(sql,sizeof(sql));strcpy(sql,"create table if not exists registeredUsr(id char primary key, passwd char);");if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }//创建已登录用户数据表bzero(sql,sizeof(sql));strcpy(sql,"create table if not exists loadedUsr(id char primary key, passwd char);");if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }//创建成功return 0;
}int do_init(sqlite3 *db){if(db == NULL){printf("数据库不存在\n");return -1;}char sql[128] = "drop table dict;";char *errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }//创建成功return 0;
}//插入表格函数
int do_insert(sqlite3 *db, char * English, char *Chinese){if(db == NULL){printf("数据库不存在\n");return -1;}char sql[128] = "";snprintf(sql, sizeof(sql),"insert into dict values(\"%s\", \"%s\");",English, Chinese);char *errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }return 0;
}//TCP服务器搭建函数
int TCP_ser_set(struct sockaddr_in* psin){int sfd;if((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ERR_MSG("socket error");return -1;}int optval = 1;//允许端口快速复用if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0){ERR_MSG("setsockopt error");return -1;}//获取地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(SERIP);* psin = sin;//绑定if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("bind error");return -1;}//设为监听if(listen(sfd,128)<0){ERR_MSG("listen error");return -1;}printf("服务器搭建成功\n");return sfd;
}//回收子进程函数
void handler(int signum){while(waitpid(-1,NULL,WNOHANG)!=0);
}//子进程中的操作
void child_operate(int newfd, sqlite3 *db){//判断传入的newfd是否合法if(newfd<0){printf("连接失败\n");return;}char buf[150] = " ";//用于读取数据包中的操作码unsigned short *operatorPtr = (unsigned short*)buf;//用于登录后记录用户名,便于读写对应用户的历史记录数据库char usrname[20] = " ";//用于读取数据包中的用户名char *usrnamePtr = buf + 2;//需要后续计算得到数据包中数据的位置char *dataPtr = NULL;//获取用户名的长度int usrnameLen = 0;//定义一个变量接收返回值int res = 0;//保存命令的数组char sql[128] = " ";while(1){bzero(buf,sizeof(buf));//接收if(recv(newfd, buf, sizeof(buf), 0) == -1){ERR_MSG("recv error");break;}//获取的是用户名的长度usrnameLen = strlen(usrnamePtr);//可知数据包中数据的位置为dataPtr = usrnamePtr + usrnameLen + 1;//printf("%s\n",buf);//send(newfd,buf,sizeof(buf),0);//注册if(1 == *operatorPtr){//现在,usrnamePtr指向用户名,dataPtr是数据的起头,在注册里面,数据包应该保存用户对应的密码//检索已注册用户数据表,看看用户名是否存在res = usrname_not_reuse(db, usrnamePtr, "registeredUsr");if(-1 == res){//说明这个函数调用遇到问题//组一个返回包*operatorPtr = 7;strcpy(dataPtr,"there is something wrong");}else if(0 == res){//说明用户名已存在*operatorPtr = 7;strcpy(dataPtr,"用户名已存在");}else if(1 == res){//说明用户名不在数据库中,可以进行注册bzero(sql, sizeof(sql));snprintf(sql, sizeof(sql),"insert into registeredUsr values(\"%s\", \"%s\");",usrnamePtr, dataPtr);char *errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }*operatorPtr = 7;strcpy(dataPtr,"注册成功");}}else if(2 == *operatorPtr){//登录//现在,usrnamePtr指向用户名,dataPtr是数据的起头,在登录里面,数据包应该保存用户对应的密码//检索已登录用户数据表,看看用户名是否存在res = usrname_not_reuse(db, usrnamePtr, "registeredUsr");if(-1 == res){//说明这个函数调用遇到问题//组一个返回包*operatorPtr = 7;strcpy(dataPtr,"there is something wrong");}else if(1 == res){//说明在已注册表中未找到该用户,说明该账号还没被注册*operatorPtr = 7;strcpy(dataPtr,"该账号还未被注册,请先注册");}else if(0 == res){//说明在已注册表中找到了该用户,进行下一步登录操作res = usrname_not_reuse(db, usrnamePtr, "loadedUsr");if(-1 == res){//说明这个函数调用遇到问题//组一个返回包*operatorPtr = 7;strcpy(dataPtr,"there is something wrong");}else if(0 == res){//说明用户名已存在已登录数据表,说明用户已经登录*operatorPtr = 7;strcpy(dataPtr,"该账号已登录,请检查账号是否被盗用");}else if(1 == res){//说明该用户已注册且未登录,可以进行登录bzero(sql, sizeof(sql));char **result = NULL;int row = 0;int col = 0;char *errmsg = NULL;int flag = 0;snprintf(sql,sizeof(sql),"select id,passwd from registeredUsr;");if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){printf("%d:sqlite3_get_table error\n",__LINE__);printf("%s\n",strerror(res));break;}//遍历比较,第0行是项的名,所以从第一行开始for(int i=col; i<=row*col; i+=col){if(strcmp(*(result+i),usrnamePtr) == 0&&strcmp(*(result+i+1),dataPtr) == 0){//登录成功后要将用户数据写入已登录用户数据表bzero(sql, sizeof(sql));snprintf(sql, sizeof(sql),"insert into loadedUsr values(\"%s\", \"%s\");",usrnamePtr, dataPtr);char *errmsg = NULL;if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }//满足条件说明用户密码匹配成功,即登录成功*operatorPtr = 7;strcpy(dataPtr,"登录成功");//将登录成功的用户名保存strcpy(usrname,usrnamePtr);flag = 0;//然后应该新建一个对应用户的历史记录数据表bzero(sql, sizeof(sql));snprintf(sql, sizeof(sql),"create table if not exists %shis(ENGLISH char , TRANSLATION char, current timestamp default current_timestamp);",usrname);if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }break;}else{flag = 1;}}if(1 == flag){*operatorPtr = 7;strcpy(dataPtr,"密码错误");}}}}else if(3 == *operatorPtr){//退出//先判断该进程中usrname字符串内是否有内容,如果有的话,说明用户是异常退出,先帮用户//退出登录,再进行退出操作if(usrname[0]!=0){//usrname字符串的第一个元素不为0,说明非空,检查usrname字符串内容是否在//已登录用户信息数据表中res = usrname_not_reuse(db, usrname, "loadedUsr");if(0 == res){//说明用户还在已登录用户信息表中,说明用户确实是异常退出,先退出登录//从已登录用户数据表中,将用户名对应的项删除bzero(sql, sizeof(sql));char *errmsg = NULL;snprintf(sql,sizeof(sql),"delete from loadedUsr where id=\'%s\';",usrname);if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }//将usrname这个字符串清空bzero(usrname,sizeof(usrname));}else if(1 == res){//说明用户已经退出登录bzero(usrname,sizeof(usrname));} }//结束函数return;}else if(4 == *operatorPtr){//查询//接收到要查询的英文单词,需要在dict数据表中查找,没找到的话也应该返回一个数据提示bzero(sql, sizeof(sql));char **result = NULL;int row = 0;int col = 0;char *errmsg = NULL;int flag = 0;snprintf(sql,sizeof(sql),"select ENGLISH,TRANSLATION from dict where ENGLISH=\'%s\';",dataPtr);if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){printf("%d:sqlite3_get_table error\n",__LINE__);printf("%s\n",strerror(res));break;}*operatorPtr = 7;if(strcmp(*(result+2),dataPtr)==0){//如果查找到的因为原型与发送来的相同,说明要找的单词存在snprintf(dataPtr,128,"%s\t%s",*(result+2),*(result+3));//将对应的英文及其翻译还有当时时间记录bzero(sql, sizeof(sql));snprintf(sql, sizeof(sql),"insert into %shis values(\"%s\", \"%s\",CURRENT_TIMESTAMP);",usrname, *(result+2), *(result+3));if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }}else{//否则不存在,发送一个反馈的包strcpy(dataPtr,"抱歉该单词还未收录");}}else if(5 == *operatorPtr){//历史记录bzero(sql, sizeof(sql));char **result = NULL;int row = 0;int col = 0;char *errmsg = NULL;int flag = 0;bzero(sql, sizeof(sql));snprintf(sql,sizeof(sql),"select * from %shis;",usrname);//printf("%s\n",sql);if((res = sqlite3_get_table(db, sql, &result, &row, &col, &errmsg))!=0){printf("%d:sqlite3_get_table error\n",__LINE__);printf("%s\n",strerror(res));break;}*operatorPtr = 7;for(int i=col; i<=row*col; i+=col){*operatorPtr = 7;snprintf(dataPtr,128,"%s\t%s\t%s",*(result+i),*(result+i+1),*(result+i+2));//发送返回的数据包send(newfd, buf, sizeof(buf), 0);bzero(dataPtr,128);}}else if(6 == *operatorPtr){//退出登录//从已登录用户数据表中,将用户名对应的项删除bzero(sql, sizeof(sql));char *errmsg = NULL;snprintf(sql,sizeof(sql),"delete from loadedUsr where id=\'%s\';",usrname);if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK){printf("%d:sqlite3_exec error %s\n",__LINE__, sqlite3_errmsg(db));break; }//将usrname这个字符串清空bzero(usrname,sizeof(usrname));*operatorPtr = 7;strcpy(dataPtr,"账号成功退出登录");}else{}//发送返回的数据包send(newfd, buf, sizeof(buf), 0);}}//查询用户名是否重复函数
int usrname_not_reuse(sqlite3 *db, const char *usrname, const char *tablename){char **res = NULL;int row = 0;int col = 0;char *errmsg = NULL;//调用查询函数char sql[128] = " ";snprintf(sql,sizeof(sql),"select id from %s;",tablename);if(sqlite3_get_table(db, sql, &res, &row, &col, &errmsg)!=0){printf("%d:sqlite3_get_table error\n",__LINE__);return -1;}//遍历比较,第0行是项的名,所以从1开始for(int i=1; i<=row; i++){if(strcmp(*(res+i),usrname) == 0){//满足条件说明用户名已存在,返回0return 0;}}//遍历到结束,说明该用户名还未存在,返回1return 1;
}//TCP客户端搭建函数
int TCP_cli_set(){int cfd;if((cfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ERR_MSG("socket error");return -1;}int optval = 1;//允许端口快速复用if(setsockopt(cfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))<0){ERR_MSG("setsockopt error");return -1;}//获取地址信息结构体struct sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_port = htons(PORT);sin.sin_addr.s_addr = inet_addr(SERIP);//连接if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin))<0){ERR_MSG("connect error");return -1;}printf("客户端搭建成功\n");return cfd;
}//客户端中的操作
void cli_operate(int cfd){if(cfd<0){printf("文件描述符有误\n");return;}//菜单int opt = 0;char buf[150] = " ";unsigned short *operatorPtr = (unsigned short *)buf;//记录用户名char id[20] = " ";//记录用户名长度int idlen = 0;//记录已登录用户的用户名char loadedid[20] = " ";int loadedidlen = 0;//记录密码char passwd[20] = " ";//记录密码长度int passwdlen = 0;while(1){bzero(buf,sizeof(buf));bzero(id,sizeof(id));bzero(passwd,sizeof(passwd));system("clear");printf("****************************\n");printf("**********电子词典**********\n");printf("***********1.注册***********\n");printf("***********2.登录***********\n");printf("***********3.退出***********\n");printf("****************************\n");printf("请输入>>");scanf("%d",&opt);if(1 == opt){//注册*operatorPtr = 1;printf("请输入要注册的用户名:");while(1){scanf("%s",id);while(getchar()!=10);//记录账号长度,保证长度符合要求才能跳出循环idlen = strlen(id);if(idlen>0&&idlen<20){break;}printf("账号长度请不要超过20,请重新输入:");}printf("请输入密码:");while(1){scanf("%s",passwd);while(getchar()!=10);//记录密码长度,保证长度符合要求才能跳出循环passwdlen = strlen(passwd);if(passwdlen<20&&passwdlen>0){break;}printf("密码长度请不要超过20,请重新输入:");}//将账号写到对应位置strcpy(buf+2,id);//将密码写到对应位置strcpy(buf+3+idlen,passwd);send(cfd, buf, sizeof(buf), 0);recv(cfd, buf, sizeof(buf), 0);printf("%s\n",buf+3+idlen);}else if(2 == opt){//登录*operatorPtr = 2;printf("请输入要登录的用户名:");while(1){scanf("%s",id);while(getchar()!=10);//记录账号长度,保证长度符合要求才能跳出循环idlen = strlen(id);if(idlen>0&&idlen<20){break;}printf("账号长度请不要超过20,请重新输入:");}printf("请输入密码:");while(1){scanf("%s",passwd);while(getchar()!=10);//记录密码长度,保证长度符合要求才能跳出循环passwdlen = strlen(passwd);if(passwdlen<20&&passwdlen>0){break;}printf("密码长度请不要超过20,请重新输入:");}//将账号写到对应位置strcpy(buf+2,id);//将密码写到对应位置strcpy(buf+3+idlen,passwd);send(cfd, buf, sizeof(buf), 0);recv(cfd, buf, sizeof(buf), 0);printf("%s\n",buf+3+idlen);if(strcmp(buf+3+idlen,"登录成功")==0){strcpy(loadedid,id);loadedidlen = idlen;//将账号写到对应位置strcpy(buf+2,loadedid);printf("输入任意字符刷新>>");getchar();while(getchar()!=10);while(1){strcpy(buf+2,loadedid);system("clear");printf("****************************\n");printf("**********电子词典**********\n");printf("*****usr:%s*****\n",loadedid);printf("***********1.查询***********\n");printf("*********2.历史记录*********\n");printf("*********3.退出登录*********\n");printf("****************************\n");printf("请输入>>");scanf("%d",&opt);if(1 == opt){//查找*operatorPtr = 4;printf("请输入要查找的单词>>");scanf("%s",buf+3+loadedidlen);send(cfd, buf, sizeof(buf), 0);recv(cfd, buf, sizeof(buf), 0);printf("%s\n",buf+3+loadedidlen);}else if(2 == opt){//历史记录*operatorPtr = 5;//由于已经将用户id写入buf包中,只需将包发送即可send(cfd, buf, sizeof(buf), 0);recv(cfd, buf, sizeof(buf), 0);char *dataPtr = buf+3+loadedidlen;//应该循环接收,那么服务器发包应该在数据区写入结束标志while(*dataPtr){printf("%s\n",dataPtr);recv(cfd, buf, sizeof(buf), 0);}}else if(3 == opt){//退出登录//发送一个操作码为6的空包,向服务器提示该账号要退出登录//将记录已登录id的字符串清空,用于存储下一个登录用户id*operatorPtr = 6;send(cfd, buf, sizeof(buf), 0);recv(cfd, buf, sizeof(buf), 0);printf("%s\n",buf+3+loadedidlen);bzero(loadedid,sizeof(loadedid));loadedidlen = 0;break;}else{printf("输入不规范,亲人两行泪,请重新输入\n");}printf("输入任意字符刷新>>");getchar();while(getchar()!=10);bzero(buf,sizeof(buf));}}}else if(3 == opt){//退出//发送一个操作码为3的空包*operatorPtr = 3;send(cfd, buf, sizeof(buf), 0);break;}else{printf("输入不规范,亲人两行泪,请重新输入\n");}printf("输入任意字符刷新>>");getchar();while(getchar()!=10);}}
服务器测试文件:serDict.c:
#include<myhead.h>
#include<sqlite3.h>
#include "dict.h"int main(int argc, const char *argv[])
{//回收子进程signal(SIGCHLD,handler);//打开数据库sqlite3 * db;if(sqlite3_open("./dict.db", &db) != SQLITE_OK){printf("%d:sqlite3_open error %s\n",__LINE__, sqlite3_errmsg(db));return -1;}//初始化数据库,完成词典数据表的重载以及用户信息数据库的导入dict_init(db);struct sockaddr_in sin;socklen_t addrlen = sizeof(sin);int sfd;if((sfd = TCP_ser_set(&sin))<0){printf("服务器搭建失败");return -1;}pid_t pid;int newfd;while(1){if((newfd = accept(sfd, (struct sockaddr*)&sin, &addrlen))<0){ERR_MSG("accept error");return 0;}pid = fork();if(pid == 0){ close(sfd);printf("这是子进程\n");child_operate(newfd, db);close(newfd);//关闭数据库if(sqlite3_close(db) != SQLITE_OK){printf("%d:sqlite3_close error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }exit(EXIT_SUCCESS);}close(newfd);}//关闭数据库if(sqlite3_close(db) != SQLITE_OK){printf("%d:sqlite3_close error %s\n",__LINE__, sqlite3_errmsg(db));return -1; }close(sfd);return 0;
}
客户端测试文件:cliDict.c:
#include<myhead.h>
#include<sqlite3.h>
#include "dict.h"int cfd;//用户按下ctrl+c后给服务器发一个退出登录的包
void handlerINT(int signum){char buf[150] = " ";unsigned short *operatorPtr = (unsigned short*)buf;//发送一个操作码为3的空包,向服务器提示该账号要退出,退出功能中包含了退出登录*operatorPtr = 3;send(cfd, buf, sizeof(buf), 0);
}int main(int argc, const char *argv[])
{//用户按下ctrl+c后给服务器发一个退出登录的包signal(2,handlerINT);//调用TCP客户端搭建函数if((cfd = TCP_cli_set())<0){printf("客户端搭建失败\n");}cli_operate(cfd);close(cfd); return 0;
}
相关文章:
电子词典项目
目录 目录 头文件:dict.h: 源文件:dict.c: 服务器测试文件:serDict.c: 客户端测试文件:cliDict.c: 头文件:dict.h: #ifndef __DICT_H__ #define __DICT_H__ #include<myhead.h> #include<sqlite3.h>#de…...
SQL12 高级操作符练习(2)
描述 题目:现在运营想要找到学校为北大或GPA在3.7以上(不包括3.7)的用户进行调研,请你取出相关数据(使用OR实现) 示例:user_profile iddevice_idgenderageuniversitygpa12138male21北京大学3.423214male复旦大学4.03…...
python写代码过程中的坑230915
1.解释代码IndentationError: expected an indented block 这个错误通常是由于代码缩进错误导致的。 在Python中,代码块(如循环、条件语句、函数等)通常使用缩进来表示。因此,如果你在期望缩进的位置没有正确缩进代码,就会出现"IndentationError: expected an inden…...
SpringBoot课堂笔记20230913
本篇文章为SpringBoot学习笔记,方便自己再复习。 Maven:jar包管理工具 注解: Controller:处理http请求,返回的视图 RestController: 相当于ResponseBody和Controller一起用,返回的是json ResponseBody:返回响应内容 …...
3D数字孪生:从3D数据采集到3D内容分析
数字孪生(Digital Twin)是物理对象、流程或系统的虚拟复制品,用于监控、分析和优化现实世界的对应物。 这些数字孪生在制造、工程和城市规划等领域变得越来越重要,因为它们使我们能够在现实世界中实施改变之前模拟和测试不同的场景…...
【杂记】git管理工具的相关应用
这里记录一些用git管理工具进行开发的命令,便于自己查看,我认为下面两篇博客写的很详细,但是为了自己方便查看,所以自己写了一些命令供自己进一步理解。gitee相对git来说更方便一些(毕竟国内的不用担心墙)&…...
看好多人都在劝退学计算机,可是张雪峰又 推荐过计算机,所以计算机到底是什么样 的?
张雪峰高考四百多分,但是他现在就瞧不起400多分的学生。说难听点,六七百分的 热门专业随便报谁不会啊? 计算机专业全世界都是过剩的,今年桂林电子科技,以前还是华为的校招大学,今年 计算机2/3待业。这个世…...
leetcode 26.删除有序数组中的重复项
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做…...
jitsi音视频会议集成到自己的网页中
将jitsi视频会议集成到自己的web网站: 源码: <!DOCTYPE html> <html lang"en" xmlns:th"http://www.thymeleaf.org"> <head><meta charset"UTF-8"><meta name"viewport" content&…...
浅析Java责任链模式实现
一、概要 定义:责任链模式是一种行为设计模式, 允许你将请求沿着处理者链进行发送。收到请求后, 每个处理者均可对请求进行处理, 或将其传递给链上的下个处理者。 二、应用场景: 1.多条件流程判断:权限相关…...
SpringBoot雪花算法主键ID传到前端后精度丢失问题的解决
Java后端Long类型的范围 -263~263,即:-9223372036854775808~9223372036854775807,它是19位的。 这个数字可以通过方法获得:Long.MAX_VALUE、Long_MIN_VALUE。 前端JS的数字类型的范围 -253~253,即:-9007…...
vue使用elementUI的upload上传文件封装
这篇文章的目的 将文件上传的方法封装一下,供大家统一调用, 话不多说,直接上代码 upload 核心参数说明 action 上传的地址accept 接受上传的文件类型multiple 是否开启多文件上传模式limit 限制上传个数fileList 文件列表disabled 是否禁用 upload 核心方…...
cenos自动启动tomcat
首先创建一个脚本 关闭tomcat 等待2分钟 启动tomcat 并且把日志输出在 /usr/local/tomcat/tomcatchognqi.log #!/bin/bashexport JAVA_HOME/usr/local/jdk/jdk1.8.0_211 export JRE_HOME$JAVA_HOME/jre# 日志文件路径和文件名 LOG_FILE"/usr/local/tomcat/tomcatchognqi.…...
OSI模型与数据的封装
1、OSI模型 上层|| 七层模型 四层模型|| 应用层| 表示层 应用层 http/ftp/ssh/ftps| 会话层 -----------------------------------------------------------------------| 传输层 传输层 tcp/udp ------------------------------…...
【李沐深度学习笔记】数据操作
本课观看地址 数据操作p1 N维数组样例 N维数组是机器学习和神经网络的主要数据结构 1-d向量就是样本的各特征抽象成一个向量;2-d矩阵的每一行是一个样本,每一行都是一个样本的特征向量 3-d可以表示RGB图片,RGB图像是一个三维数组ÿ…...
【蓝桥杯选拔赛真题61】Scratch小猫照镜子 少儿编程scratch图形化编程 蓝桥杯选拔赛真题解析
目录 scratch小猫照镜子 一、题目要求 编程实现 二、案例分析 1、角色分析...
vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题)
vue3将页面导出成PDF文件(完美解决图片、表格内容分割问题) 1、安装依赖2、在utils中创建htmlToPDF.js文件3、在vue中引入并使用 1、安装依赖 npm install --save html2canvas // 页面转图片 npm install jspdf --save // 图片转pdf2、在utils中创建h…...
软件测试:黑盒测试用例的四种设计方法
一、输入域测试用例设计方法 输入域测试法是一种综合考虑了等价类划分、边界值分析等方法的综合方法,针对输入域测试法中可能出现的各种情况,输入域测试法主要考虑三个方面: (1)极端测试(ExtremalTesting),要求在输入域中选择测…...
数据库开发-MySQL基础DQL和多表设计
1. 数据库操作-DQL DQL英文全称是Data Query Language(数据查询语言),用来查询数据库表中的记录。 1.1 介绍 查询关键字:SELECT 查询操作是所有SQL语句当中最为常见,也是最为重要的操作。在一个正常的业务系统中,查询操作的使…...
PowerDesigner 逆向工程以及IDEA中UML插件
1、MySQL数据库连接(JDBC方式) 1.1 新建一个pdm,dbms选择mysql 1.2 Database - Connect 选择数据库连接 1.3 配置连接信息 数据库连接这里是通过一个配置文件来获取连接信息的,首次的话因为没有,所以我们需要选择…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error
在前端开发中,JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作(如 Promise、async/await 等),开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝(r…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
