Linux下使用消息队实现 ATM 自动取款机功能

文章分五部分:需求分析、项目所需知识点、思路讲解、代码实现、功能演示
本文内容较长,建议是按照我自己的思路给大家讲解的,如果有其他问题,欢迎评论区讨论
文章中的代码是在linux下编译实现的,注意自己的环境。

(一)需求分析

我们的ATM终端要求实现下面的功能:

  • (1)开户
  • (2)存款
  • (3)取款
  • (4)查询
  • (5)转账
  • (6)退出
  • (7)销户

(二)项目相关知识点

  • 文件操作
  • 进程通信----消息队列
  • 模块编程
  • 数据库
    上面的内容不再讲解,根据代码可以查看相关函数的功能。

(三)思路讲解

1、实现功能用到进程间通信
(1)通信要求两个进程实现
            两个进程分别完成什么任务??站在用户的角度去考虑这个问题:例如:你去银行开户的场景你:我要开户银行职员:请出示你的相关信息你:交出身份证	银行职员:开始一系列的操作(录入信息,开账户等),紧接着要求你输入密码你:输入密码银行职员:请确认密码你:再次输入银行职员:银行卡余额不能为空,请存款你:交出100元银行职员:拿走你的钱,在你的账户输入100........................从这个角度来讲你和银行职员就是两个不同的进程,你们分别的任务有:银行职员根据你的提示信息为你开户、存款、取款、查询、转账、退出、销户操作,而你要做的就是给出相应的操作提示
(2)进程间通信的选取
消息队列在进程通信比较有代表性,我们在这里使用消息对列。

2、进程任务分解

可以将进程分为客户端进程和服务端进程,分别的任务有:
服务端进程

   1) 首先用msgget函数创建两个消息队列消息队列1:存放客户端进程发来的各种请求注意:根据操作的不同,会发送不同类型的消息,可以自己定义消息的类型,另外可以将功能函数作为一个模块,这样会使得程序逻辑比较清晰消息队列2:存放服务端进程回复给客户端进程的消息2)利用fork函数创建进程父进程阻塞就行,子进程通过exec函数来调用函数功能模块的可执行文件3)捕获用户发来的Ctrl+c的信号,结束进程 并删除消息队列通过exit函数和msgctl功能函数实现模块功能编写:1)开户操作首先需要一个文件来保存用户的信息,同时检测该文件是否已经存在---------------注意:银行账号不能重复成功创建文件后将客户端进程发来的用户信息写入文件返回成功的消息类型给客户端2)存款操作根据用户信息找到对应的文件,将文件内的关于金额的值加上相应的取款金额3)取款操作根据用户信息找到对应的文件,将文件内的关于金额的值减去相应的取款金额4)转账操作转账操作需要输入两个先关的用户信息,之后就是取款操作和存款操作的结合5)删除账户操作根据提示信息,找到相对应的文件,先要情况账户中的余额才能注销账户

客户端进程

可以先写一个界面,类似C语言的学员管理系统
根据界面的操作提示选择相对应的功能
操作有:(1)开户(2)存款(3)取款(4)查询(5)转账(6)退出(7)销户
实现:首先要获取消息队列1)开户操作开户的时候榕湖需要输入用户的相关信息(账户、密码、存款金额)为了操作简便可以通过结构体来封装用户信息输入信息操作后将消息发送到消息队列,并指定消息类型2)存款向指定的账户存入指定的金额先输入用户相关信息将信息发送到消息队列,并指定消息类型3)取款先输入用户相关信息和取款金额将信息发送到消息队列,并指定消息类型4)查询先输入用户相关信息将信息发送到消息队列,并指定消息类型5)转账先输入当前用户相关信息和要转账到的用户信息将信息发送到消息队列,并指定消息类型6)转账先输入销毁用户信息将信息发送到消息队列,并指定消息类型
以上操作只需要简单的录入信息和发送消息到消息队列,如同你现在按取款机上对应的功能键,具体操作在客户端调用的功能模块实现

(四)代码实现

由于代码量比较大这里贴出客户端和服务端的代码,其余的代码在链接资源里有需要的自行下载
client.c

/************************************************************************
*
* 文件名:cLient.c
*
* 文件描述:模拟银行终端客户端
*
* 创建人:Liu ming 2020/2/13
*
* 版本号:2.0
*
* 修改记录:
*
************************************************************************/
#define DEBUG  1 //调试定义宏
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include "msg_queue.h"
//#define   CLIENT     0
#ifdef  CLIENT
int show_flag = 0;//0--未登录界面  1--登录后界面
int sig_flag =0;//选择的功能id号
int msg_sendid =0,msg_recvid=0;//消息队列id
struct signal signal_t= {0,0}; //初始化进程通信信号/*================================================================
*
* 函 数 名:Ctrl_c
*
* 参 数: 任意整形
*
* 功能描述:  强制结束函数时删除消息队列
*
* 返 回 值:无
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
void Ctrl_c(int singal_num)
{system("pkill server");msgctl(msg_sendid,IPC_RMID,NULL);msgctl(msg_recvid,IPC_RMID,NULL);exit(0);
}/*================================================================
*
* 函 数 名:is_ok
*
* 参 数: 客户端请求码
*
* 功能描述:  如果用户输入1,则请求码被传递到消息队列结构体并调用handle()进行发送接收处理;输入其他不做任何操作
*
* 返 回 值:  0 ------输入了确认-1-------输入了取消
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
int is_ok(int flag)
{int num=0;//提示用户进行输入printf("输入 1 进行确认,输入 2 退出操作: \n");scanf("%d",&num);if(num !=1){printf("请重新选择~\n");return -1;}sig_flag = flag ;handle();//退出登录账号 清除结构体if(sig_flag == 3 || sig_flag == 1){InitMsg_t(&signal_t,1);//销户后清除客户端信息}return 0;
}
/*================================================================
*
* 函 数 名:handle
*
* 参 数: 无
*
* 功能描述:  发送请求功能码,接收服务端的数据,处理返回的数据
*
* 返 回 值:无
*
* 抛出异常:
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
void handle()
{signal_t.num = sig_flag;//复制请求码到消息队列
#ifdef DEBUGprintf("send operation code : %d\n",signal_t.num);
#endifmsgsnd(msg_sendid,(const void *)&signal_t,sizeof(signal_t)-4,0);//发送消息请求msgrcv(msg_recvid,(void *)&signal_t,sizeof(signal_t)-4,0,0);//阻塞接收消息
#ifdef DEBUGprintf("receive operation code : %d\n",signal_t.num);
#endif//根据接收功能码处理不同的信息switch(signal_t.num){case 30://开户成功printf("姓名:%s\n",signal_t.name);printf("身份证号:%s\n",signal_t.identyCard);printf("手机号码:%s\n",signal_t.phone);printf("分配的银行卡号:%d\n",signal_t.id);break;case 60://开户失败printf("请输入正确的身份信息\n");break;case 31://登录--账号密码正确show_flag =1;//进入登录界面break;case 61://登录--账号错误show_flag =0;//进入登录界面printf("账号或密码错误,请重试\n");break;case 62://登录--密码错误show_flag =0;//进入登录界面printf("账号或密码错误,请重试\n");break;case 32://销户--成功show_flag =0;//进入登录界面break;case 63://销户--失败printf("销户失败,请重试!\n");break;case 33://存款--成功show_flag =1;//printf("存款成功,当前余额为:%f\n",signal_t.money);break;case 64://存款--失败printf("存款失败,请重试!\n");break;case 34://取款--成功show_flag =1;//printf("取款成功,取出:%f\n",signal_t.money);break;case 65://取款--失败printf("取款失败,请重试!\n");break;case 35://转账--成功show_flag =1;//printf("转账成功,转出:%f\n",signal_t.money);break;case 66://余额不足printf("余额不足,请重试!\n");break;case 67://银行卡号不存在printf("银行卡号不存在,请重试!\n");break;case 36://余额查询--成功printf("余额:%f\n",signal_t.money);break;case 68://余额查询--失败printf("销户失败,请重试!\n");break;default:printf("传输信息出错!\n");break;}
}/*================================================================
*
* 函 数 名:menu
*
* 参 数:无
*
* 功能描述:  提供显示和选择功能,并根据选择调用handle()函数
*                     进行数据的发送接收处理
* 返 回 值:无
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
void menu()
{int num=0;while(1){
#ifdef DEBUGprintf("showflag=%d\t signalflag=%d\n",show_flag,sig_flag);
#endifswitch(show_flag){case 0: //界面一 主界面printf("+-------------------------------------------------------------+\n");printf("|                                                             | \n");printf("|                 Welcome to bank system                      | \n");printf("|                                                             | \n");printf("|                      1.登录                                 | \n");printf("|                      2.开户                                 | \n");printf("|_____________________________________________________________| \n");printf("choose->");scanf("%d",&num);switch(num){case 1:{show_flag =3;//进入登录页面}break;case 2:{show_flag =2;//进入开户界面}break;default :printf("请重新输入!\n");}break;case 1://界面二  登录进去后printf("+-------------------------------------------------------------+\n");printf("|                                                             | \n");printf("|                 Welcome to bank system                      | \n");printf("|                                                             | \n");printf("|                      0.退出                                 | \n");printf("|                      1.销户                                 | \n");printf("|                      2.存款                                 | \n");printf("|                      3.取款                                 | \n");printf("|                      4.转账                                 | \n");printf("|                      5.余额查询                             | \n");printf("|_____________________________________________________________| \n");printf("choose->");scanf("%d",&num);switch(num){case 0://退出show_flag = 0;InitMsg_t(&signal_t,1);//初始化结构体break;case 1://销户is_ok(3);//3为销户请求码break;case 2://存款printf("请输入存款金额:");scanf("%f",&signal_t.money);is_ok(4);//4为存款请求码break;case 3://取款printf("请输入取款金额:");scanf("%f",&signal_t.money);//发送取款请求码5is_ok(5);break;case 4://转账printf("请输入转账账号:");scanf("%d",&signal_t.tmpId);printf("请输入转账金额:");scanf("%f",&signal_t.money);is_ok(6);//6为转账请求码break;case 5://余额查询sig_flag = 7;handle();break;default:printf("请重新输入!\n");}break;case 2://界面三  开户界面printf("+-------------------------------------------------------------+\n");printf("                    正在进行开户操作...                         \n");printf("请输入姓名:");scanf("%s",signal_t.name);printf("请输入身份证号:");scanf("%s",signal_t.identyCard);printf("请输入手机号码:");scanf("%s",signal_t.phone);printf("请输入密码:");scanf("%s",signal_t.passwd);is_ok(1);//1为开户请求码show_flag =0;//  if(! is_ok(1))sig_flag =0;break;case 3 :     //界面四  登录界面printf("+-------------------------------------------------------------+\n");printf("                  Welcome to bank system                       \n");printf("请输入账号:");scanf("%d",&signal_t.id);printf("请输入密码:");scanf("%s",signal_t.passwd);if(is_ok(2)){sig_flag =0;show_flag=0;InitMsg_t(&signal_t,1);//清除结构体}break;}}
}int main(int argc, char *argv[])
{signal(SIGINT,Ctrl_c);//强制退出时删除开辟的资源msg_sendid= get_msg(123);//获得发送消息对列msg_recvid= get_msg(456);//获得接收消息对列InitMsg_t(&signal_t,1);//初始化消息类型1menu();return 0;
}
#endif

server.c

/************************************************************************
*
* 文件名:cLient.c
*
* 文件描述:模拟银行终端客户端
*
* 创建人:Liu ming 2020/2/13
*
* 版本号:2.0
*
*注释 :
---------------------------------------------------------------------------------------------------------
*     操作  客户端(client) 请求功能码       服务端(server)      **    开户                 01                                      成功返回30  失败返回60*    登录                 02                                      成功返回31  卡号错误61,密码错误62*    销户                 03                                      成功返回32  失败返回63*    存款                 04                                      成功返回33  失败返回64*    取款                 05                                      成功返回34  失败返回65*    转账                 06                                      成功返回35  余额不足返回66 转账账号不存在67*    余额查询         07                                      成功返回36  失败返回68--------------------------------------------------------------------------------------------------------
* 修改记录:
*
************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include "mysql.h"
#include "msg_queue.h"#define DEBUG 1#ifdef SERVER
int num =000;//分配的卡号
int sig_flag =0;//选择功能id号
char sql_buf[1024];//sql语句存放数组
struct signal signal_t= {0,0}; //进程通信信号
int msg_sendid=0,msg_recvid=0;//消息队列id
/*================================================================
*
* 函 数 名:give_account
*
* 参 数:无
*
* 功能描述: 查询数据库中最后一个id,把id+1作为新账户分配下去.
*
* 返 回 值:成功卡号,失败-1
*
* 抛出异常:
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
int give_account()
{memset(sql_buf,0,sizeof(sql_buf));//清除数组中的内容strcpy(sql_buf,"select cast(id as unsigned integer) from bank order by date desc ");errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));if(errno){printf("getid query error!\n");mysql_close(pmysql);exit(0);}res = mysql_store_result(pmysql);if(res ==NULL){printf("没有获取到有效id\n");return -1;}row = mysql_fetch_row(res);num = 1+ atoi(row[0]);//返回生成的号码return num;}/*================================================================
*
* 函 数 名:Ctrl_c
*
* 参 数: 任意整形
*
* 功能描述:  强制结束函数时删除消息队列
*
* 返 回 值:无
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
void Ctrl_c(int singal_num)
{system("pkill client");msgctl(msg_sendid,IPC_RMID,NULL);msgctl(msg_recvid,IPC_RMID,NULL);exit(0);
}/*================================================================
*
* 函 数 名:query_money
*
* 参 数: @id -- 银行卡卡号
*
* 功能描述: 根据输入的银行卡卡号查询余额
*
* 返 回 值:返回查询的余额
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
float query_money(int id)
{sprintf(sql_buf,"select money from bank where id=%d",id);errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));memset(sql_buf,0,sizeof(sql_buf));if(errno){printf("query money error!");signal_t.num = 67;//余额查询失败return -1;}res = mysql_store_result(pmysql);row = mysql_fetch_row(res);return atoi(row[0]);
}/*================================================================
*
* 函 数 名:insert_money
*
* 参 数: @id -- 银行卡卡号@money ---金额
*
* 功能描述: 根据输入的银行卡卡号修改用户余额
*
* 返 回 值:成功返回0,失败返回-1
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
int insert_money(int id,float money)
{sprintf(sql_buf,"update bank set money= %f where id = %d",money,id);errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));memset(sql_buf,0,sizeof(sql_buf));if(errno){printf("update money error!");return -1;}return 0;}
/*================================================================
*
* 函 数 名:handle
*
* 参 数: 无
*
* 功能描述:  处理客户端发来的功能请求
*
* 返 回 值:无
*
* 作 者:Liu ming 2020/2/13
*
================================================================*/
void handle(void)
{float tmp_money=0;sig_flag = signal_t.num;printf("接收操作码:%d\n",sig_flag);switch(sig_flag){case 1://开户操作printf("---------------------------------\n");printf("姓名:%s\n",signal_t.name);printf("身份证号:%s\n",signal_t.identyCard);printf("手机号码:%s\n",signal_t.phone);//生成卡号signal_t.id =give_account();if(signal_t.id <0){perror("give_account()\n");return ;}printf("生成的id:%d\n",signal_t.id);//存储信息到数据库memset(sql_buf,0,sizeof(sql_buf));sprintf(sql_buf,"insert into bank values(%d,'%s',%s,%s,%s,%s,now())",\signal_t.id,signal_t.name,"1",signal_t.phone,signal_t.identyCard,signal_t.passwd);errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));#ifdef DEBUGprintf("%s\n",sql_buf);#endif // DEBUGif(errno){printf("insert card info  error!");signal_t.num =60;//卡号输入错误}else{signal_t.num = 30;//分配卡号正确}break;case 2://登录操作memset(sql_buf,0,sizeof(sql_buf));sprintf(sql_buf,"select passwd from bank where id=%d",signal_t.id);errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));if(errno){printf("query passwd error!");return;}res = mysql_store_result(pmysql);row = mysql_fetch_row(res);if(row == 0){signal_t.num =61;//查询信息出错无此人}else{if(strcmp(row[0],signal_t.passwd)==0){printf("账号密码正确\n");signal_t.num = 31;//账号密码正确}else{signal_t.num = 62;//密码错误printf("密码错误");}}break;case 3://销户//删除数据库制定的信息memset(sql_buf,0,sizeof(sql_buf));sprintf(sql_buf,"delete from bank where id = %d",signal_t.id);#ifdef DEBUGprintf("sql[]=%s\n",sql_buf);#endif // DEBUGerrno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));if(errno){printf("delete card info  error!");signal_t.num =63;//删除信息出错}else{signal_t.num = 32;//删除成功}break;case 4://存款//查询余额tmp_money=query_money(signal_t.id);//修改余额tmp_money += signal_t.money;//存入数据库if(insert_money(signal_t.id,tmp_money)==0){signal_t.money = tmp_money;signal_t.num =33;}elsesignal_t.num=64;break;case 5://取款//查询余额tmp_money=query_money(signal_t.id);//修改余额if(tmp_money<=signal_t.money){signal_t.money = tmp_money;tmp_money=0;}else{tmp_money -= signal_t.money;}//存入数据库if(insert_money(signal_t.id,tmp_money)==0){signal_t.num =34;}elsesignal_t.num=65;break;case 6://转账sprintf(sql_buf,"select money from bank where id=%d",signal_t.tmpId);errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));memset(sql_buf,0,sizeof(sql_buf));if(errno){printf("query passwd error!");return;}res = mysql_store_result(pmysql);row = mysql_fetch_row(res);if(row == 0){signal_t.num =67;// 银行卡卡号不存在}else{tmp_money=query_money(signal_t.id);//修改余额if(tmp_money<=signal_t.money){signal_t.num = 66;//余额不足}else{signal_t.num = 35;//余额不足tmp_money -= signal_t.money;insert_money(signal_t.id,tmp_money);//扣除转账账户的余额tmp_money=query_money(signal_t.tmpId);tmp_money += signal_t.money;insert_money(signal_t.tmpId,tmp_money);//增加被转账账户的余额}}break;case 7://查询余额tmp_money=query_money(signal_t.id);printf("your money : %f\n",tmp_money);signal_t.money = tmp_money;signal_t.num = 36;//余额查询成功break;default :break;}
}int main(int argc, char *argv[])
{signal(SIGINT,Ctrl_c);//强制退出时删除消息对列//连接数据库pmysql = connect_mysql("test");//检测某表是否存在指定数据库中errno =table_isExist(pmysql,"bank");if(errno){// talbe is not exist,//create table in hear !char buf[]="create table bank(id int not null auto_increment primary key , name varchar(20) not null, \money float default 0,phone varchar(11) not null,identyCard varchar(18) not null unique,\passwd varchar(20) not null,date DATETIME )";//执行创建表格MySQL语句errno = mysql_real_query(pmysql,buf,strlen(buf));//插入一条默认数据char test[]="insert into bank values(1,'admin',0,'null','admin','666666',now())";errno = mysql_real_query(pmysql,test,strlen(test));//设置可以存储中文memset(sql_buf,0,sizeof(sql_buf));sprintf(sql_buf,"alter table %s  CONVERT TO CHARACTER SET utf8","bank");errno = mysql_real_query(pmysql,sql_buf,strlen(sql_buf));#ifdef DEBUGprintf("the table is not exist ,creating success!\n");#endif // DEBUG}else{#ifdef DEBUGprintf("the table is exist \n");#endif // DEBUG}msg_recvid = get_msg(123);//获得接收消息队列msg_sendid = get_msg(456);//获得发送消息队列while(1){printf("----------------------------------------\n");printf("等待接受信息:\n");msgrcv(msg_recvid,(void *)&signal_t,sizeof(signal_t)-4,0,0);#ifdef DEBUGprintf("receive operation code : %d\nname=%s\niddentCar=%s\nphone=%s\npasswd=%s\nid=%d\nmoney=%f\n",signal_t.num,signal_t.name,signal_t.identyCard,signal_t.phone,signal_t.passwd,signal_t.id,signal_t.money);#endif // DEBUGhandle();//处理接收的信息printf("send operation code : %d\n",signal_t.num);msgsnd(msg_sendid,(const void *)&signal_t,sizeof(signal_t)-4,0);//0队列满时阻塞}return 0;
}

(五)功能演示

开户功能演示:
开户
存款功能演示:
存款
其他功能就不演示了,感兴趣可以下载代码自己尝试。

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

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

相关文章

200行代码实现视频人物实时去除

今天在GitHub上发现了一个好玩的代码&#xff0c;短短几百行代码就实现了从复杂的背景视频中去除人物&#xff0c;不得不说这位大佬比较厉害。 这个项目只需要在网络浏览器中使用JavaScript&#xff0c;用200多行TensorFlow.js代码&#xff0c;就可以实时让视频画面中的人物对…

codeforces C. Vanya and Scales

C. Vanya and ScalesVanya has a scales for weighing loads and weights of masses w0, w1, w2, ..., w100 grams where w is some integer not less than 2(exactly one weight of each nominal value). Vanya wonders whether he can weight an item with mass m using …

菱形继承和虚继承、对象模型和虚基表

1.菱形继承&#xff08;钻石继承&#xff09;&#xff1a;两个子类继承同一父类&#xff0c;而又有子类同时继承这两个子类。例如B,C两个类同时继承A&#xff0c;但是又有一个D类同时继承B,C类。 2.菱形继承的对象模型 class A { public:int _a; };class B :public A { p…

c++虚函数和虚函数表

前言 &#xff08;1&#xff09;虚基表与虚函数表是两个完全不同的概念 虚基表用来解决继承的二义性(虚基类可以解决)。虚函数用来实现泛型编程&#xff0c;运行时多态。 &#xff08;2&#xff09;虚函数是在基类普通函数前加virtual关键字&#xff0c;是实现多态的基础 &a…

VS2017安装配置Qt

这篇文章作为qt的开发环境配置篇&#xff0c;记录如何在vs2017中安装qt的 所需软件下载链接如下&#xff1a; QT下载链接&#xff1a;QT visual studio下载链接&#xff1a;visual studio 这里推荐安装最新的&#xff0c;原因是vs2017不支持一些老版本的makefile文件生成&#…

STM32位带区和位带别名区的浅谈

1.首先谈下为什么要使用位带&#xff1f; 在学习51单片机时就已经使用过位操作&#xff0c;比如使用sbit对单片机IO口的定义&#xff0c;但是STM32中并没有这类关键字&#xff0c;而是通过访问位带别名区来实现&#xff0c;即通过将每个比特位膨胀成一个32位字&#xff0c;当访…

Hibernate的数据查找,添加!

1.首先看一下测试数据库的物理模型 2.测试所需要的Hibernate的jar包 3.数据库的sql /**/ /* DBMS name: MySQL 5.0 */ /* Created on: 2015/7/3 23:17:57 */ /**/drop table if exists books;drop tab…

新手如何在Altium Designer中绘制电路板

好久没用AD画电路板了&#xff0c;这次电子实训让画个PCB板&#xff0c;借着这个机会写了一篇新手教程。 此教程所用的电路图是自动循迹小车&#xff0c;虽然元件比较简单&#xff0c;但是感觉还是很厉害的&#xff0c;一块看一下吧。 此教程仅适用于没有基础的同学 一、概述 …

Qt模仿QQ登录界面(一)

这两天研究qt&#xff0c;练习时做了个仿QQ登录界面&#xff0c;我这次实现的比较简单&#xff0c;先在这里记录一下&#xff0c;以后有空了会继续完善的。 &#xff08;一&#xff09;效果图 这里使用我的qq号测试的如图&#xff1a; &#xff08;二&#xff09;工程文件 &…

回流焊和波峰焊的区别

本文首先分别介绍回流焊和波峰焊的特点&#xff0c;然后对两者进行比较&#xff0c;欢迎评论补充哦~ 最近在实习看到了厂里面的回流焊的波峰焊&#xff0c;有点好奇就查了点资料&#xff0c;分享给同样爱学习的你。 一.回流焊 一般的表面贴装工艺分三步&#xff1a;印刷机施加…

三对角矩阵的压缩

三对角矩阵&#xff0c;从第二行开始选中的元素的个数都为3个。对于a[i,j]将要存储的位置k&#xff0c;首先前(i-1)行元素的个数是(i-2)*3 2(第一行元素的个数为2)&#xff0c;又a[i,j]属于第i行被选中元素的第j-i1个元素&#xff0c;所以k (i-2)*3 2 j-i1 2*ij-3 如果知道了…

LC和RC滤波电路分析

一、概述 整流电路的输出电压并不是纯粹的直流&#xff0c;从示波器观察整流电路的输出&#xff0c;与直流相差很大&#xff0c;波形中含有较大的脉动成分&#xff0c;称为纹波。为了获得比较理想的直流电压&#xff0c;需要利用具有储能作用的电抗性元件(如&#xff1a;电感、…

dev c++ Boost库的安装

dev c 的boost库的安装步骤 然后点击“check for updates”按钮 最后点击“Download selected”按钮&#xff0c;下载完成后安装.... 给dev添加boost库文件&#xff0c;找到之前安装的目录 #include<iostream> #include<string> #include<cstring> #include…

(一)C语言之数据类型

在这里主要讲了基本的知识&#xff0c;具体练习时注意用代码看看数据存储的位数和大小&#xff0c;像char a127;aa1;这时候a的值。可以用sizeof查看数据类型占的字节数。以及不同数据类型之间如何自动转换和强制转换&#xff0c;还有printf和scanf的具体用法&#xff0c;多动手…

十字链表的应用

#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #define MAX_VERTEX_NUM 20 using namespace std; typedef struct ArcBox{int tailVex, headVex;//该弧的尾和头顶点的位置 struct ArcBox *hlink, *tlink;//分别为弧…

(二)C语言数据类型(2)

今天主要总结了一下运算符&#xff0c;详细介绍了运算符分类和优先级的基本知识 欢迎加入嵌入式学习群&#xff1a;559601187 运算符按操作数可以分为&#xff1a;单目运算符、双目运算符和三目运算符&#xff0c;优先级依次为单目运算符>双目运算符>三目运算符,在c语言里…

AOE网的关键路径的计算

求关键路径&#xff0c;只需理解顶点&#xff08;事件&#xff09;和边&#xff08;活动&#xff09;各自的两个特征属性以及求法即可&#xff1a; 先根据首结点的Ve(j)0由前向后&#xff08;正拓扑序列&#xff09;计算各顶点的最早发生时间 再根据终结点的Vl(j)等于它的V…

(三)C语言之九条语句

今天来说一下我们以后可能用的最多的C语言语句&#xff1a;条件语句、循环语句、控制语句。理论很简单&#xff0c;注重多自己写代码才能熟练运用。 欢迎加入嵌入式学习群&#xff1a;559601187 一起愉快的玩耍啊~ &#xff08;一&#xff09;条件语句 &#xff08;1&#xff…

次优查找树的建立

查找效率最高即平均查找长度最小&#xff0c;根据前面所学知识&#xff0c;我们可以给出有序表在非等概率情况下应遵循的两个原则&#xff1a; 1、最先访问的结点应是访问概率最大的结点&#xff1b; 2、每次访问应使结点两边尚未访问的结点的被访概率之和尽可能相等。 这两…

平衡二叉树AVL插入

平衡二叉树(Balancedbinary tree)是由阿德尔森-维尔斯和兰迪斯(Adelson-Velskiiand Landis)于1962年首先提出的&#xff0c;所以又称为AVL树。 定义&#xff1a;平衡二叉树或为空树,或为如下性质的二叉排序树: &#xff08;1&#xff09;左右子树深度之差的绝对值不超过1; &…