电子词典项目
目录
目录
头文件: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 配置连接信息 数据库连接这里是通过一个配置文件来获取连接信息的,首次的话因为没有,所以我们需要选择…...
企业架构LNMP学习笔记56
MongoDB数据类型操作:CURD 1、添加数据: mongodb里存储数据的格式文档形式,以bson格式的文档形式。 创建数据库: > use tp5shop switched to db tp5shop > db.getName() tp5shop使用切换库,不存在自动创建&am…...
[Linux入门]---搭建Linux环境
1.Linux环境的搭建方式 使用Linux操作系统的三种途径: 1.直接安装在物理机上,但是由于 Linux 桌面使用起来非常不友好,不推荐。 2.使用虚拟机软件,将 Linux 搭建在虚拟机上,但是由于当前的虚拟机软件(如 VMWare 之类的…...
性能测试知多少---性能分析与调优的原理
最近一直纠结性能分析与调优如何下手,先从硬件开始,还是先从代码或数据库。从操作系统(CPU调度,内存管理,进程调度,磁盘I/O)、网络、协议(HTTP, TCP/IP )&…...
“对象创建”模式
通过“对象创建”模式绕开new,来避免对象创建 (new) 过程中所导致的紧耦合(依赖具体类)从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 典型模式 Factory MethodAbstract FactoryPrototypeBuilder Factory Method 动机 (Motivation) 在软件系统中&am…...
ipad手写笔有必要买吗?好用的平板触控笔
众所周知,随着Apple pencil的出现,市面上出现越来越多平替电容笔的出现,无论是价格和功能,几乎都很接近。很多小伙伴不知如何下手,不知道如何从众多品牌中挑选出适合自己的电容笔,今天我为大家总结一下网上…...
OpenGL ES视频特效开发参考Shadertoy参数详解参考Godot文档
今天一个大厂的学员过来问shadertoy上一些参数的问题,因为我之前用过一段时间Godot引擎, 我清晰记得Godot官方文档有明确的解释,所以整理下发给做特效的同学。 Shadertoy是一个网站,它方便用户编写片段着色器并创造出纯粹的魔法。…...
java:逆序排序的三种方法
// 逆序第一种方法 public static void main(String[] args) {int arr[] {11, 22, 33, 44, 55, 66};for (int i arr.length-1; i > 0; i--) {System.out.print("\t"arr[i]);}}缺点:这个是直接逆转,如果里面是随机数没办法比较 逆序第二种…...
pgsql操作json类型
目录 一、表结构 二、实体类 三、json处理器 四、配置文件 五、josn数据 1、插入 2、查找 一、表结构 CREATE TABLE "public"."pg_user" ("id" int8 NOT NULL GENERATED ALWAYS AS IDENTITY ( INCREMENT 1 MINVALUE 1 MAXVALUE 92233720…...
Thinkphp6 配置并使用redis图文详解 小皮面板
这篇文章主要介绍了Thinkphp6 配置并使用redis的方法,结合实例形式详细分析了Redis的安装、配置以及thinkphp6操作Redis的基本技巧,需要的朋友可以参考下 一、安装redis ThinkPHP内置支持的缓存类型包括file、memcache、wincache、sqlite。ThinkPHP默认使用自带的采用think\Ca…...
模拟实现链式二叉树及其结构学习——【数据结构】
W...Y的主页 😊 代码仓库分享 💕 之前我们实现了用顺序表完成二叉树(也就是堆),顺序二叉树的实际作用就是解决堆排序以及Topk问题。 今天我们要学习的内容是链式二叉树,并且实现链式二叉树,这篇博客与递归息息相关&a…...
长沙网站建设价格/网站设计与制作教程
2019独角兽企业重金招聘Python工程师标准>>> http://smallcultfollowing.com/babysteps/blog/categories/rust/ 转载于:https://my.oschina.net/innovation/blog/150099...
南京网站建设多少钱/西安seo公司
本文仅代表 Phodal 的个人观点,来听听一个前端程序员的 YY。新一期的ThoughtWorks技术雷达有点出乎意料,使用new标签的框架、工具、技术、语言等等超过了一半——Vue.js、ES2017上榜,Three.js凭着VR的火又上榜了,还有熟悉的Electr…...
做网上卖酒的网站有几家/seo模拟点击
H参数表示色彩信息,即所处的光谱颜色的位置。该参数用一角度量来表示,红、绿、蓝分别相隔120度。互补色分别相差180度。纯度S为一比例值,范围从0到1,它表示成所选颜色的纯度和该颜色最大的纯度之间的比率。S0时,只有灰…...
石家庄网站建设德信互联科技有限公司/全球十大搜索引擎排名及网址
本文和大家重点讨论一下Perl模块的应用,多数大型程序都分割成多个部件,每一部件通常含有一个或多个子程序及相关的变量,执行特定的一个或多个任务。集合了变量和子程序的部件称为程序Perl模块。 Perl模块 1、创建Perl模块 Perl5中用包来创建P…...
抽奖机网站怎么做/2023年火爆的新闻
太让人郁闷了,没想到竟然有人会兴师动众的用DDos攻击个人电脑,SynFlood这东西很久以前有玩过,不过被当作攻击目标确实是第一次,感觉还真是不一样。不过结果有点惨了,不是开8000端口的程序崩溃,而是阻止攻击…...