23.2.28 Staffing System

news2025/2/28 6:39:32

员工管理系统功能介绍:

1)服务器负责管理所有员工表单(以数据库形式),其他客户端可通过网络连接服务器来查询员工表单。

2)需要账号密码登陆,其中需要区分管理员账号还是普通用户账号。

3)管理员账号可以查看、修改、添加、删除员工信息,同时具有查询历史记录功能,管理员要负责管理所有的普通用户。

4)普通用户只能查询修改与本人有关的相关信息,其他员工信息不得查看修改。

5)服务器能同时相应多台客户端的请求功能。并发

1 流程图

服务器:

客户端:

 

2 通信结构体

typedef struct staff_info{

int no; //员工编号

int usertype; //ADMIN 0 USER 1

char name[NAMELEN]; //姓名

char passwd[8]; //密码

int age; // 年龄

char phone[NAMELEN];//电话

char addr[DATALEN]; // 地址

char work[DATALEN]; //职位

char date[DATALEN]; //入职年月

int level; // 等级

double salary ; // 工资

}staff_info_t;

/定义双方通信的结构体信息/

typedef struct {

int msgtype; //请求的消息类型

int usertype; //ADMIN 1 USER 2

char username[NAMELEN]; //姓名

char passwd[8]; //登陆密码

char recvmsg[DATALEN]; //通信的消息

int flags; //标志位

staff_info_t info; //员工信息

}MSG;

3 所需知识点

自动探测

自动换行

【1】TCP通信的编程步骤

  1.服务器:

 1)创建套接字

 2)绑定ip和端口号

 3)监听

 4)等待客户端连接

 int main() 

 { 

//1.创建套接字 

int sockfd = socket(); 

//2.初始化通信结构 

struct sockaddr_in addr; 

addr.sin_family=AF_INET; 

addr.sin_port = port; 

addr.sin_addr=addr; 

bind(sockfd, &addr); 

//3.监听 

listen(); 

//4.连接 

while(1) 

int connfd = accept(); 

//5.循环数据收发 

while(1) 

recv(); 

send(); 

close(sockfd); 

close(connfd); 

 } 

  2.客户端:

 1)创建套接字

 2)连接服务器

 int main() 

 { 

//1.创建套接字 

int sockfd = socket(); 

//2.初始化通信结构 

struct sockaddr_in addr; 

addr.sin_family=AF_INET; 

addr.sin_port = port; 

addr.sin_addr=addr; 

//3.连接 

connect(); 

//5.循环数据收发 

while(1) 

send(); 

recv(); 

 } 

【2】服务器模型

 1.循环服务器

 2.并发服务器

 1)多线程

 2)多进程

 3)IO多路复用:

a. select:

基本思想:

1. 先构造一张有关文件描述符的表(集合、数组); fd_set fd; 

2. 将你关心的文件描述符加入到这个表中;FD_SET(); 

3. 然后调用一个函数。 select / poll

4. 当这些文件描述符中的一个或多个已准备好进行I/O操作的时候

该函数才返回(阻塞)。

5. 判断是哪一个或哪些文件描述符产生了事件(IO操作); 

6. 做对应的逻辑处理; 

****select函数返回之后,会自动将除了产生事件的文件描述符以外的位全部清空; 

程序步骤:

1.把关心的文件描述符放入集合--FD_SET

2.监听集合中的文件描述符--select 

3.依次判断哪个文件描述符有数据--FD_ISSET

4.依次处理有数据的文件描述符的数据

伪代码:

fd_set fd; 

FD_SET(sockfd); 

while(1) { 

设置监听读写文件描述符集合(FD_*); 

调用select; 

select();

如果是监听套接字就绪,说明有新的连接请求

if(sockfd) 

建立连接(); 

int connfd = accept(); 

加入到监听文件描述符集合; 

FD_SET(connfd); 

}否则说明是一个已经连接过的描述符

else 

进行操作(send或者recv); 

recv(); 

send(); 

}

select弊端:

1. 一个进程最多只能监听1024个文件描述符 (千级别)

2. select是一种轮询的机制; 

3. 涉及到用户态和内核态的数据拷贝; 

b. poll

1. 优化文件描述符个数的限制; 

2. poll是一种轮询的机制; 

3. 涉及到用户态和内核态的数据拷贝; 

函数接口:   

int poll(struct pollfd *fds, nfds_t nfds, int timeout); 

参数:

struct pollfd *fds

关心的文件描述符数组struct pollfd fds[N]; 

nfds:个数

timeout: 超市检测

毫秒级的:如果填1000,1秒

 如果-1,阻塞

问题:

我想检测是键盘事件(标准输入 文件描述如为0 ),

还是鼠标事件(文件描述符是/dev/input/mouse1);  

1. 创建一个结构体数组

struct pollfd fds[2]; 

2. 将你关心的文件描述符加入到结构体成员中

struct pollfd { 

  int   fd;         // 关心的文件描述符; 

  short events;     // 关心的事件,读 

  short revents;    // 如果产生事件,则会自动填充该成员的值 

}; 

// 键盘 

fds[0].fd = 0; 

fds[0].events = POLLIN; 

//鼠标 

fds[1].fd = mouse1_fd; 

fds[1].events = POLLIN; 

3. 调用poll函数

如果返回表示有事件产生; 

poll(fds,2,1000) 

4. 判断具体是哪个文件描述符产生了事件

if(fds[0].revents == POLLIN) 

.... 

c. epoll

1. 没有文件描述符的限制

2. 异步IO,当有事件产生,文件描述符主动调用callback

3. 不用数据拷贝; 

3个功能函数:

#include <sys/epoll.h> 

int epoll_create(int size);//创建红黑树根节点 

//成功时返回epoll文件描述符,失败时返回-1 

//控制epoll属性 

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 

epfd:epoll_create函数的返回句柄。

op:表示动作类型。有三个宏 来表示:

EPOLL_CTL_ADD:注册新的fd到epfd中

EPOLL_CTL_MOD:修改已注册fd的监听事件

EPOLL_CTL_DEL:从epfd中删除一个fd

FD:需要监听的fd。

event:告诉内核需要监听什么事件

EPOLLIN:表示对应文件描述符可读

EPOLLOUT:可写

EPOLLPRI:有紧急数据可读;

EPOLLERR:错误;

EPOLLHUP:被挂断;

EPOLLET:触发方式,电平触发;

ET模式:表示状态的变化;

//成功时返回0,失败时返回-1 

//等待事件到来 

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 

功能:等待事件的产生,类似于select嗲用

epfd:句柄;

events:用来从内核得到事件的集合;

maxevents:表示每次能处理事件最大个数;

timeout:超时时间,毫秒,0立即返回,-1阻塞

//成功时返回发生事件的文件描述数,失败时返回-1 

伪代码:

1.定义epoll事件,创建epoll的fd

int epfd,epct,i; 

struct epoll_event event;       //定义epoll 事件 

struct epoll_event events[20];  //定义epoll 事件集合 

epfd = epoll_create(1); // 创建epoll 的fd  

2.填充事件

event.data.fd = serverFd;           //填充事件的fd 

event.events = EPOLLIN | EPOLLET;   //填充 事件类型  

epoll_ctl(epfd,EPOLL_CTL_ADD,serverFd,&event);  //把serverFd(监听FD)注册到epfd中 

3.监听事件

while(1){

epct = epoll_wait(epfd,events,20,-1); // 等待事件到来,阻塞模式  

for(i=0;i<epct;i++){  //根据epoll返回的值来查询事件  

if(events[i].data.fd == serverFd){ // 如果事件的fd是监听fd,调用accept处理 

clientFd = accept(); 

//添加clientfd描述符 

epoll_ctl(epfd,EPOLL_CTL_ADD,clientFd,&event);

}else {  

//如果不是serverFd,应是client数据事件,调用读数据 

read(); 

}

【3】数据库函数接口

 1.int   sqlite3_open(char  *path,   sqlite3 **db);        

功能:打开sqlite数据库  

参数:

path: 数据库文件路径         

db: 指向sqlite句柄的指针     

返回值:成功返回0,失败返回错误码(非零值) 

 2.int   sqlite3_close(sqlite3 *db); 

功能:关闭sqlite数据库

    返回值:成功返回0,失败返回错误码

 3.int sqlite3_exec(sqlite3 *db, const  char  *sql,  

sqlite3_callback callback, void *,  char **errmsg); 

功能:执行SQL语句

参数:

db:数据库句柄

         sql:SQL语句 ("create table stu .....;") 

         callback:回调函数

void * arg:

当使用查询命令的时候,callback和arg才有意义;

select .....

         errmsg:错误信息指针的地址

char *errmsg;    

&errmsg; 

返回值:成功返回0,失败返回错误码

 int callback(void *para, int f_num, char **f_value, char **f_name); 

功能:每找到一条记录自动执行一次回调函数

参数:

para:   传递给回调函数的参数

f_num:  记录中包含的字段数目(id name score)

相当于有多少列; 

f_value:包含每个字段值的指针数组

f_name:包含每个字段名称的指针数组

返回值:成功返回0,失败返回-1 

 4.int  sqlite3_get_table(sqlite3 *db, const  char  *sql, 

char ***resultp,  int *nrow,  int *ncolumn, char **errmsg); 

    功能:执行SQL操作

参数:

db:数据库句柄

sql:SQL语句

resultp:用来指向sql执行结果的指针;实际上就是“指针数组指针”;

nrow:满足条件的记录的数目,实际上就是有多少行数据; 

ncolumn:每条记录包含的字段数目,实际上就是有多少个字段(多少列); 

errmsg:错误信息指针的地址

    返回值:成功返回0,失败返回错误码

练习:创建数据库stu.db,包含name、id、score字段,实现对数据库的增删改查。

【4】员工管理系统

  1.通信结构体的定义(5min)

  2.服务器负责处理操作

客户端不能直接操作数据库

 common.h

#ifndef _COMMON_H_
#define _COMMON_H_

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sqlite3.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sqlite3.h>
#include <netinet/in.h>
#include <sys/select.h>
#include <pthread.h>

#define STAFF_DATABASE 	 "staff_manage_system.db"

#define USER_LOGIN 		0x00000000  // login	登陆    0x00000001
#define USER_MODIFY 	0x00000001  // user-modification  修改
#define USER_QUERY 		0x00000002  // user-query   查询

#define ADMIN_LOGIN 	0x10000000  // login	登陆    0x00000001
#define ADMIN_MODIFY 	0x10000001 // admin_modification
#define ADMIN_ADDUSER 	0x10000002 // admin_adduser
#define ADMIN_DELUSER 	0x10000004 // admin_deluser
#define ADMIN_QUERY 	0x10000008  //hitory_query
#define ADMIN_HISTORY 	0x10000010  //hitory_query

#define QUIT 			0x11111111

#define ADMIN 0	//管理员
#define USER  1	//用户

#define NAMELEN 16
#define DATALEN 128

/*员工基本信息*/
typedef struct staff_info{
	int  no; 			//员工编号
	int  usertype;  	//ADMIN 1	USER 2	 
	char name[NAMELEN];	//姓名
	char passwd[8]; 	//密码
	int  age; 			// 年龄
	char phone[NAMELEN];//电话
	char addr[DATALEN]; // 地址
	char work[DATALEN]; //职位
	char date[DATALEN];	//入职年月
	int level;			// 等级
	double salary ;		// 工资
	
}staff_info_t;

/*定义双方通信的结构体信息*/
typedef struct {
	int  msgtype;     //请求的消息类型
	int  usertype;    //ADMIN 1	USER 2	   
	char username[NAMELEN];  //姓名
	char passwd[8];			 //登陆密码
	char recvmsg[DATALEN];   //通信的消息
	int  flags;      //标志位
	staff_info_t info;      //员工信息
}MSG;

#endif

Makefile

all:
	gcc server.c -o server -lpthread -lsqlite3
	gcc client.c -o client

clean:
	rm server client

 client.c

#include "common.h"

/**************************************
 *函数名:do_query
 *参   数:消息结构体
 *功   能:登陆
 ****************************************/
void do_admin_query(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);



}

/**************************************
 *函数名:admin_modification
 *参   数:消息结构体
 *功   能:管理员修改
 ****************************************/
void do_admin_modification(int sockfd,MSG *msg)//管理员修改
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);


}

/**************************************
 *函数名:admin_adduser
 *参   数:消息结构体
 *功   能:管理员创建用户
 ****************************************/
void do_admin_adduser(int sockfd,MSG *msg)//管理员添加用户
{		
	printf("------------%s-----------%d.\n",__func__,__LINE__);
}

/**************************************
 *函数名:admin_deluser
 *参   数:消息结构体
 *功   能:管理员删除用户
 ****************************************/
void do_admin_deluser(int sockfd,MSG *msg)//管理员删除用户
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}

/**************************************
 *函数名:do_history
 *参   数:消息结构体
 *功   能:查看历史记录
 ****************************************/
void do_admin_history (int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}

/**************************************
 *函数名:admin_menu
 *参   数:套接字、消息结构体
 *功   能:管理员菜单
 ****************************************/
void admin_menu(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);
}

/**************************************
 *函数名:do_query
 *参   数:消息结构体
 *功   能:登陆
 ****************************************/
void do_user_query(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}

/**************************************
 *函数名:do_modification
 *参   数:消息结构体
 *功   能:修改
 ****************************************/
void do_user_modification(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}

/**************************************
 *函数名:user_menu
 *参   数:消息结构体
 *功   能:管理员菜单
 ****************************************/
void user_menu(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);
	
}

int admin_or_user_login(int sockfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);
	//输入用户名和密码
	memset(msg->username, 0, NAMELEN);
	printf("请输入用户名:");
	scanf("%s",msg->username);
	getchar();

	memset(msg->passwd, 0, DATALEN);
	printf("请输入密码(6位)");
	scanf("%s",msg->passwd);
	getchar();

	//发送登陆请求
	send(sockfd, msg, sizeof(MSG), 0);
	//接受服务器响应
	recv(sockfd, msg, sizeof(MSG), 0);
	printf("msg->recvmsg :%s\n",msg->recvmsg);

	//判断是否登陆成功
	if(strncmp(msg->recvmsg, "OK", 2) == 0)
	{
		if(msg->usertype == ADMIN)
		{
			printf("亲爱的管理员,欢迎您登陆员工管理系统!\n");
			admin_menu(sockfd,msg);
		}
		else if(msg->usertype == USER)
		{
			printf("亲爱的用户,欢迎您登陆员工管理系统!\n");
			user_menu(sockfd,msg);
		}
	}
	else
	{
		printf("登陆失败!%s\n", msg->recvmsg);
		return -1;
	}

	return 0;
}


/************************************************
 *函数名:do_login
 *参   数:套接字、消息结构体
 *返回值:是否登陆成功
 *功   能:登陆
 *************************************************/
int do_login(int sockfd)
{	
	int n;
	MSG msg;

	while(1){
		printf("*************************************************************\n");
		printf("********  1:管理员模式    2:普通用户模式    3:退出********\n");
		printf("*************************************************************\n");
		printf("请输入您的选择(数字)>>");
		scanf("%d",&n);
		getchar();

		switch(n)
		{
			case 1:
				msg.msgtype  = ADMIN_LOGIN;
				msg.usertype = ADMIN;
				break;
			case 2:
				msg.msgtype =  USER_LOGIN;
				msg.usertype = USER;
				break;
			case 3:
				msg.msgtype = QUIT;
				if(send(sockfd, &msg, sizeof(MSG), 0)<0)
				{
					perror("do_login send");
					return -1;
				}
				close(sockfd);
				exit(0);
			default:
				printf("您的输入有误,请重新输入\n"); 
		}

		admin_or_user_login(sockfd,&msg);
	}

}

int main(int argc, const char *argv[])
{
	//socket->填充->绑定->监听->等待连接->数据交互->关闭 

	//创建网络通信的套接字

	//填充网络结构体

	//连接服务器
	if(connect() == -1){
		perror("connect failed.\n");
		exit(-1);
	}

	do_login(sockfd);

	close(sockfd);

	return 0;
}

 server.c

#include "common.h"

sqlite3 *db;  //仅服务器使用

int process_user_or_admin_login_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);
	//封装sql命令,表中查询用户名和密码-存在-登录成功-发送响应-失败-发送失败响应	
	char sql[DATALEN] = {0};
	char *errmsg;
	char **result;
	int nrow,ncolumn;

	msg->info.usertype =  msg->usertype;
	strcpy(msg->info.name,msg->username);
	strcpy(msg->info.passwd,msg->passwd);
	
	printf("usrtype: %#x-----usrname: %s---passwd: %s.\n",msg->info.usertype,msg->info.name,msg->info.passwd);
	sprintf(sql,"select * from usrinfo where usertype=%d and name='%s' and passwd='%s';",msg->info.usertype,msg->info.name,msg->info.passwd);
	if(sqlite3_get_table(db,sql,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK){
		printf("---****----%s.\n",errmsg);		
	}else{
		//printf("----nrow-----%d,ncolumn-----%d.\n",nrow,ncolumn);		
		if(nrow == 0){
			strcpy(msg->recvmsg,"name or passwd failed.\n");
			send(acceptfd,msg,sizeof(MSG),0);
		}else{
			strcpy(msg->recvmsg,"OK");
			send(acceptfd,msg,sizeof(MSG),0);
		}
	}
	return 0;	
}

int process_user_modify_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}



int process_user_query_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}


int process_admin_modify_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}


int process_admin_adduser_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}



int process_admin_deluser_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}


int process_admin_query_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}

int process_admin_history_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}


int process_client_quit_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);

}


int process_client_request(int acceptfd,MSG *msg)
{
	printf("------------%s-----------%d.\n",__func__,__LINE__);
	switch (msg->msgtype)
	{
		case USER_LOGIN:
		case ADMIN_LOGIN:
			process_user_or_admin_login_request(acceptfd,msg);
			break;
		case USER_MODIFY:
			process_user_modify_request(acceptfd,msg);
			break;
		case USER_QUERY:
			process_user_query_request(acceptfd,msg);
			break;
		case ADMIN_MODIFY:
			process_admin_modify_request(acceptfd,msg);
			break;

		case ADMIN_ADDUSER:
			process_admin_adduser_request(acceptfd,msg);
			break;

		case ADMIN_DELUSER:
			process_admin_deluser_request(acceptfd,msg);
			break;
		case ADMIN_QUERY:
			process_admin_query_request(acceptfd,msg);
			break;
		case ADMIN_HISTORY:
			process_admin_history_request(acceptfd,msg);
			break;
		case QUIT:
			process_client_quit_request(acceptfd,msg);
			break;
		default:
			break;
	}

}


int main(int argc, const char *argv[])
{
	//判断命令行参数	
	
	//打开数据库
	if(sqlite3_open() != SQLITE_OK){
		printf("%s.\n",sqlite3_errmsg(db));
	}else{
		printf("the database open success.\n");
	}

	//执行数据库操作
	if(sqlite3_exec()!= SQLITE_OK){
		printf("%s.\n",errmsg);
	}else{
		printf("create usrinfo table success.\n");
	}
	
	//socket->填充->绑定->监听->等待连接->数据交互->关闭

	//创建网络通信的套接字
	sockfd = socket();
	if(sockfd == -1){
		perror("socket failed.\n");
		exit(-1);
	}
	
	//填充网络结构体	

	//绑定网络套接字和网络结构体
	if(bind() == -1){
		printf("bind failed.\n");
		exit(-1);
	}

	//监听套接字,将主动套接字转化为被动套接字
	if(listen() == -1){
		printf("listen failed.\n");
		exit(-1);
	}

	//通过select实现并发

	while(1){
		retval =select();
		//判断是否是集合里关注的事件
		if(判断是连接请求){
			//数据交互 
			acceptfd = accept();
			if(acceptfd == -1){
				printf("acceptfd failed.\n");
				exit(-1);
			}					
		}else{
			recvbytes = recv();
			if(recvbytes == -1){
				printf("recv failed.\n");
				continue;
			}else if(recvbytes == 0){
				printf("peer shutdown.\n");
				close(i);
				FD_CLR(i, &readfds);  //删除集合中的i
			}else{
				process_client_request(i,&msg);
			}
		}
	}
	close(sockfd);

	return 0;
}

 


以下为员工管理系统带调试信息的打印记录:
	管理员登陆:
		客户端的打印信息
		服务器端的打印信息
		
	普通员工登陆:
		客户端的打印信息
		服务器端的打印信息
		

@@@@@@@@@@@@@@@@@@@@@@管理员登陆--客户端的测试记录:@@@@@@@@@@@@@@@@@@@@@@

linux@ubuntu:/mnt/hgfs/KernelSource/staff_manage_select/stage4-user$ ./client
sockfd :3.
*************************************************************
********  1:管理员模式    2:普通用户模式    3:退出********
*************************************************************
请输入您的选择(数字)>>1
------------admin_or_user_login-----------489.
请输入用户名:admin
请输入密码(6位)admin
msg->recvmsg :OK
亲爱的管理员,欢迎您登陆员工管理系统!


*************************************************************
* 1:查询  2:修改 3:添加用户  4:删除用户  5:查询历史记录*
* 6:退出													*
*************************************************************
请输入您的选择(数字)>>1
------------do_admin_query-----------35.
*************************************************************
******* 1:按人名查找  	2:查找所有 	3:退出	 *******
*************************************************************
请输入您的选择(数字)>>1
请输入您要查找的用户名:xiaohui
工号	用户类型	 姓名	密码	年龄	电话	地址	职位	入职年月	等级	 工资
======================================================================================
1004,    1,    xiaohui,    1,    31,    1888x,    henan,    gagagaga,    9012.10.11,    1,    1.0;.
*************************************************************
******* 1:按人名查找  	2:查找所有 	3:退出	 *******
*************************************************************
请输入您的选择(数字)>>2
工号	用户类型	 姓名	密码	年龄	电话	地址	职位	入职年月	等级	 工资
======================================================================================
1001,    0,    admin,    admin,    18,    110,    华清远见创客学院,    嵌入式物联网方向讲师,    xxx,    5,    1.0;.
======================================================================================
1003,    1,    fengjunhui,    1,    30,    18888888888,    henan,    gaga,    2015.10.23,    1,    10.0;.
======================================================================================
1002,    1,    lisi,    1,    20,    119,    华清远见创客学院=北京,    ooo,    2019.11.11,    1,    50.0;.
======================================================================================
1004,    1,    xiaohui,    1,    31,    1888x,    henan,    gagagaga,    9012.10.11,    1,    1.0;.
*************************************************************
******* 1:按人名查找  	2:查找所有 	3:退出	 *******
*************************************************************
请输入您的选择(数字)>>3


*************************************************************
* 1:查询  2:修改 3:添加用户  4:删除用户  5:查询历史记录*
* 6:退出													*
*************************************************************
请输入您的选择(数字)>>2
------------do_admin_modification-----------100.
请输入您要修改只认的工号:1002
*******************请输入要修改的选项********************
******	1:姓名	  2:年龄	3:家庭住址   4:电话  ******
******	5:职位	   6:工资  7:入职年月   8:评级  ******
******	9:密码	 10:退出				  *******
*************************************************************
请输入您的选择(数字)>>2
请输入年龄:30 
数据库修改成功!修改结束.

 

 

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

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

相关文章

聚观早报 | 苹果2024年放弃高通;腾讯回应进军类 ChatGPT

今日要闻&#xff1a;苹果2024年放弃高通&#xff1b;腾讯回应进军类 ChatGPT&#xff1b;小米发布无线AR眼镜探索版&#xff1b;50%的美国企业已在使用ChatGPT&#xff1b;Snap推出ChatGPT驱动的聊天机器人 苹果2024年放弃高通 高通公司 CEO 兼总裁克里斯蒂亚诺・安蒙&#xf…

Node.js 是个啥?

趣学 Node.js - 死月 - 掘金小册带你重新体悟 Node.js 之美。「趣学 Node.js」由死月撰写&#xff0c;1923人购买https://s.juejin.cn/ds/SYVvuDw/ 在这里&#xff0c;我们先装作对 Node.js 不了解&#xff0c;从头来过吧。你有没有假装不了解 Node.js 我不知道&#xff0c;但…

界面开发(2)--- 使用PyQt5制作用户登陆界面

使用PyQt5制作用户登陆界面 上篇文章已经介绍了如何配置PyQt5环境&#xff0c;这篇文章在此基础上展开&#xff0c;主要记录一下如何使用 PyQt5 制作用户登陆界面&#xff0c;并对一些基础操作进行介绍。 下面是具体步骤&#xff0c;一起来看看吧&#xff01; 1. 打开 Pychar…

【IoT】2023裁员潮还在继续,构建规划能力也许是一剂良方

今天要分享的主题是华为的市场管理方法论。 市场管理这个词总体来说还是有些抽象&#xff0c;本质上来看或者说从个人的角度来看&#xff0c;其实就是一种规划的能力。 无论是创业&#xff0c;还是作为职场人&#xff0c;规划能力必将是你不可或缺的一种基础能力。 尤其是在这样…

Maven说明

目录 1.说明 2.详细说明 3.Maven模型 4.Maven常用的命令 5.Maven生命周期 6.Maven坐标 7.依赖管理与依赖范围 1.说明 Maven是专门用于管理和构建Java项目的工具&#xff0c;它是基于项目对象模型(POM)的概念&#xff0c;主要功能有&#xff1a; 提供了一套标准化的项目…

Ubuntu 下NGINX 的简单使用

1.NGINX的安装与卸载 1.1.安装NGINX apt-get install nginx1.2.NGINX操作命令 service nginx start #启动 service nginx reload #重新加载配置文件 service nginx restart #重启 service nginx status #查看运行状态 1.3.卸载NGINX apt-get remove nginx nginx-common #…

28 openEuler管理网络-配置主机名

文章目录28 openEuler管理网络-配置主机名28.1 简介28.2 使用hostnamectl配置主机名28.2.1 查看所有主机名28.2.2 设定所有主机名28.2.3 设定特定主机名28.2.4 清除特定主机名28.2.5 远程更改主机名28.3 使用nmcli配置主机名28 openEuler管理网络-配置主机名 28.1 简介 hostn…

XXL-JOB的基本使用

1、执行器 1.1下边配置执行器 下边配置执行器&#xff0c;执行器负责与调度中心通信接收调度中心发起的任务调度请求。 1、首先在媒资管理模块的service工程添加依赖&#xff0c;在项目的父工程已约定了版本2.3.1 XML <dependency><groupId>com.xuxueli</gro…

【Web安全社工篇】——水坑攻击

作者名&#xff1a;白昼安全主页面链接&#xff1a; 主页传送门创作初心&#xff1a; 以后赚大钱座右铭&#xff1a; 不要让时代的悲哀成为你的悲哀专研方向&#xff1a; web安全&#xff0c;后渗透技术每日鸡汤&#xff1a;努力赚钱不是因为爱钱“水坑攻击”&#xff0c;黑客攻…

CVPR 2023 接收结果出炉!再创历史新高!录用2360篇!(附10篇最新论文)

点击下方卡片&#xff0c;关注“CVer”公众号AI/CV重磅干货&#xff0c;第一时间送达点击进入—>【计算机视觉】微信技术交流群2023 年 2 月 28 日凌晨&#xff0c;CVPR 2023 顶会论文接收结果出炉&#xff01;这次没有先放出论文 ID List&#xff0c;而是直接 email 通知作…

【C语言】位段

位段 一.简介 位段和结构体很相似。不同的是&#xff1a; 位段的成员&#xff1a;成员名 : 数字且其成员必须是整型(char、int、unsigned int……) 示例&#xff1a; struct S {char a : 3;char b : 2;char c : 7; };S就是一个位段类型&#xff0c;其成员a为占3个比特位的…

【趣味学Python】Python基础语法讲解

目录 编码 标识符 python保留字 注释 实例(Python 3.0) 实例(Python 3.0) 行与缩进 实例(Python 3.0) 实例 多行语句 数字(Number)类型 字符串(String) 实例(Python 3.0) 空行 等待用户输入 实例(Python 3.0) 同一行显示多条语句 实例(Python 3.0) 多个语句构…

【Day02数据结构 空间复杂度】

最近太忙了都好久没有更新博客了,太难了,抽空水一篇文章,大佬们多多支持. 上篇:时间复杂度分析 目录 前言 一、空间复杂度概念&#xff1f; 二、实例展示 三、.有复杂度要求的算法题练习 1.题目链接&#xff1a;力扣--消失的数字 2.题目链接&#xff1a;力扣--旋转数组 总结: 1…

去课工场成都基地学Java,可行吗?

当然可行&#xff0c;不管是你选择自学Java&#xff0c;还是去培训机构学习都是非常不错的职业选择。选择好赛道能让你的未来收获更多。 2023年了&#xff0c;随着数字经济的发展&#xff0c;互联网已经渗入我们生活工作的方方面面&#xff0c;现在即使是吃个饭点个餐很多时候…

SpringBoot解决跨域方式

跨域是指在 Web 应用中&#xff0c;一个服务器资源或应用访问另一个服务器资源或应用的资源时候。由于浏览器的同源策略&#xff0c;一般情况下同一个域中的网站或应用可以互相访问资源&#xff0c;但跨域访问会被浏览器拒绝。浏览器出于安全考虑&#xff0c;会限制跨域访问&am…

深度学习领域的多任务学习综述

文章目录前言1. 什么是多任务学习&#xff1f;2. 为何要使用多任务学习&#xff1f;3. 多任务学习有哪些类型&#xff1f;3.1 基于硬参数共享的多任务学习3.2 基于软参数共享的多任务学习4. 为什么多任务学习能提升模型的性能&#xff1f;4.1 隐藏数据扩充&#xff08;Implicit…

关于sudo配置

前言这里做一个小补充&#xff0c;主要讲一下关于利用sudo对指令提权以及普通用户无法使用sudo指令的问题。在前面的文章【Linux】一文掌握Linux权限中&#xff0c;我们讲到了关于权限的一些问题。我们知道root身份下&#xff0c;一切畅通无阻&#xff0c;而权限只是用来限制我…

urp SpotLight 衰减方式扩展

背景&#xff1a; 解决默认spotLight 的衰减模式下&#xff0c; 在距离灯光特别近的时候&#xff0c;灯光过爆的情况 解决方法&#xff1a; 修改SpotLight的衰减方式 下图是unity给出的几种衰减模式以及图示&#xff1a; 其中InverseSquare是当前2021.2 unity版本中urp(12.1…

相恨见晚的办公插件神器,颠覆我们对辅助工具的认知

不坑盒子 这是一个非常好用的插件工具&#xff0c;专门应用在Word文档和wps&#xff0c;支持Office 2010以上的版本&#xff0c;操作也简单且实用。 不坑盒子下载及使用说明 一键排版功能 像是下面的自动排版功能&#xff0c;可以在配置里面先设定好需要的格式&#xff0c;…

结合java中的锁聊聊锁的本质

在操作系统里面&#xff0c;也会遇到什么信号量、互斥量&#xff0c;然后说利用互斥量、信号量可以实现锁的功能&#xff0c;而操作系统提供的原语有又mutex锁在学习数据库的时候&#xff0c;什么表锁、行锁、读锁、写锁、排它锁、意向锁、meta锁等等&#xff0c;各种各样的锁的…