网络版ATM项目的实现——客户端

网络版的ATM实现思路

客户端

  1 #include "customer.h"
  2 
  3 static int sockfd;
  4 
  5 /*int create_msg_queue_c(int key)
  6 {
  7     //创建消息队列
  8     int msgid = msgget(key,IPC_CREAT|0644);
  9     if(0 > msgid)
 10     {
 11         perror("msgget");
 12         return -1;
 13     }
 14     return msgid;
 15 }*/
 16 
 17 void show_menu(void)
 18 {
 19     printf("Welcome to Online Bank !\n");
 20     printf("---------------------\n");
 21     printf("    [1]开户        \n");
 22     printf("    [2]登录        \n");
 23     printf("    [3]解锁        \n");
 24     printf("    [4]销户        \n");
 25     printf("    [5]退出        \n");
 26     printf("---------------------\n");
 27 }
 28 //开户界面
 29 void open_menu(void)
 30 {
 31     
 32     Msg msg = {99};
 33     //得到基本信息
 34     printf("请输入姓名:");
 35     gets(msg.acc.name);
 36     printf("请输入身份证号:");
 37     gets(msg.acc.idcard);
 38     printf("请输入预存金额:");
 39     scanf("%f",&msg.acc.money);
 40     //清空缓冲区
 41     stdin->_IO_read_ptr = stdin->_IO_read_end;
 42     strcpy(msg.acc.password,"123456");
 43     printf("%d\n",msg.acc.account);
 44     //将获得的基本信息发送到服务端
 45     send(sockfd,&msg,sizeof(Msg),0);
 46     //接收服务端传回的信息(账号id)
 47     recv(sockfd,&msg,sizeof(Msg),0);
 48     //perror("msgrcv");
 49     printf("*****您的id是%d,初始密码为123456,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
 50     sleep(2);
 51 }
 52 //显示登陆后的功能界面
 53 void func_menu(void)
 54 {
 55     printf("Welcome to Online Bank !\n");
 56     printf("---------------------\n");
 57     printf("    [1]存款        \n");
 58     printf("    [2]取款        \n");
 59     printf("    [3]转账        \n");
 60     printf("    [4]查询        \n");
 61     printf("    [5]修密        \n");
 62     printf("    [6]退出        \n");
 63     printf("---------------------\n");
 64 }
 65 //退出登录
 66 void logout(int id)
 67 {
 68     
 69     Msg msg = {50};
 70     msg.acc.account = id;
 71     send(sockfd,&msg,sizeof(Msg),0);
 72     //接收服务端传回的信息(账号id)
 73     recv(sockfd,&msg,sizeof(Msg),0);
 74     printf("退出成功!\n");
 75     sleep(2);
 76 }
 77 //存钱界面
 78 void save(int id)
 79 {
 80     Msg msg = {5};
 81     msg.acc.account = id;
 82     printf("请输入要存的金额:");
 83     scanf("%f",&msg.acc.money);
 84     //清空缓冲区
 85     stdin->_IO_read_ptr = stdin->_IO_read_end;
 86     //将获得的基本信息发送到服务端
 87     send(sockfd,&msg,sizeof(Msg),0);
 88     //接收服务端传回的信息(账号id)
 89     recv(sockfd,&msg,sizeof(Msg),0);
 90     printf("存款成功!\n");
 91     printf("*****您的id是%d,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
 92     sleep(2);
 93 }
 94 //取款界面
 95 void take(int id)
 96 {
 97     Msg msg = {6};
 98     msg.acc.account = id;
 99     printf("请输入要取的金额:");
100     scanf("%f",&msg.acc.money);
101     //清空缓冲区
102     stdin->_IO_read_ptr = stdin->_IO_read_end;
103     //将获得的基本信息发送到服务端
104     send(sockfd,&msg,sizeof(Msg),0);
105     //接收服务端传回的信息(账号id)
106     recv(sockfd,&msg,sizeof(Msg),0);
107     if(-1 == msg.acc.flag)
108     {
109         printf("取款失败!\n");
110         sleep(2);
111     }
112     else
113     {
114         printf("取款成功!\n");
115         printf("*****您的id是%d,账号内的余额为%f*****\n",msg.acc.account,msg.acc.money);
116         sleep(2);
117     }
118 }
119 //转账界面
120 void trans(int id)
121 {
122     Msg msg1 = {7};
123     //Msg msg2 = {17};
124     msg1.acc.account = id;
125     printf("请输入转账对象的id:");
126     scanf("%d",&msg1.acc.target);
127     //清空缓冲区
128     stdin->_IO_read_ptr = stdin->_IO_read_end;
129     printf("请输入要转账的金额:");
130     scanf("%f",&msg1.acc.money);
131     //清空缓冲区
132     stdin->_IO_read_ptr = stdin->_IO_read_end;
133     //将获得的基本信息发送到服务端
134     send(sockfd,&msg1,sizeof(Msg),0);
135     //接收服务端传回的信息(账号id)
136     recv(sockfd,&msg1,sizeof(Msg),0);
137     switch(msg1.acc.flag)
138     {
139         case -1:printf("您的余额不足!\n");sleep(2);break;
140         case -2:printf("转账对象不存在!\n");sleep(2);break;
141         case 0:    printf("转账成功!\n");
142                 printf("*****您的id是%d,账号内的余额为%f*****\n",msg1.acc.account,msg1.acc.money);
143                 sleep(2);break;
144     }
145 }
146 
147 //查询界面
148 void show(int id)
149 {
150     system("clear");
151     Msg msg = {8};
152     msg.acc.account = id;
153     //将获得的基本信息发送到服务端
154     send(sockfd,&msg,sizeof(Msg),0);
155     //接收服务端传回的信息(账号id)
156     recv(sockfd,&msg,sizeof(Msg),0);
157     printf("%s用户您好!\n",msg.acc.name);
158     printf("账号ID:%d\n",msg.acc.account);
159     printf("身份证号:%s\n",msg.acc.idcard);
160     printf("账号余额:%f\n",msg.acc.money);
161     printf("*****按任意键返回*****\n");
162     getchar();    
163 }
164 
165 //修改密码界面
166 void change(int id)
167 {
168     Msg msg = {9};
169     msg.acc.account = id;
170     printf("请输入您的身份账号以用于验证用户信息:");
171     gets(msg.acc.idcard);
172     printf("请输入新密码(6位):");
173     put_pw(msg.acc.password);
174     if(6 != strlen(msg.acc.password))
175     {
176         printf("密码格式不符!\n");
177         sleep(2);
178         return;
179     }
180     else
181     {
182         //将获得的基本信息发送到服务端
183         send(sockfd,&msg,sizeof(Msg),0);
184         //接收服务端传回的信息(账号id)
185         recv(sockfd,&msg,sizeof(Msg),0);
186         if(-1 == msg.acc.flag)
187         {
188             printf("修改失败!\n");
189             sleep(2);
190         }
191         else
192         {
193             printf("修改成功!\n");
194             sleep(2);
195         }
196     }
197 }
198 
199 //副主界面
200 void ano_main(int id)
201 {
202     while(1)
203     {
204         system("clear");
205         func_menu();
206         switch(getch())
207         {
208             case 49:save(id);break;
209             case 50:take(id);break;
210             case 51:trans(id);break;
211             case 52:show(id);break;
212             case 53:change(id);break;
213             case 54:logout(id);return;
214         }
215     }
216 }
217 //加载界面
218 void loading(void)
219 {
220     //system("clear");
221     char buf[103] = {};
222     memset(buf, ' ', sizeof(buf));
223     buf[0] = '[';
224     buf[101] = ']';
225     buf[102] = '\0';
226     int i = 0;
227     char index[6] = "-\\|/\0";
228     while (i <= 99)
229     {
230         buf[i+1] = '>';
231         printf("%s[%d%%][%c]\r",buf,i,index[i%4]);
232         fflush(stdout);//刷新缓冲区
233         usleep(50000);
234         i++;
235     }
236  
237     printf("\n");
238 }
239 //登录界面
240 void login_menu(void)
241 {
242     Msg msg = {2};
243     msg.acc.flag = -1;
244     //获取账号密码
245     printf("请输入账号:");
246     scanf("%d",&msg.acc.account);
247     //清空缓冲区
248     stdin->_IO_read_ptr = stdin->_IO_read_end;
249     printf("请输入密码:");
250     put_pw(msg.acc.password);
251     //将获得的基本信息发送到服务端
252     send(sockfd,&msg,sizeof(Msg),0);
253     //接收服务端传回的信息(账号id)
254     recv(sockfd,&msg,sizeof(Msg),0);
255     printf("%d\n",msg.acc.flag);
256     //根据判断结果跳转界面
257     if(0 == msg.acc.flag)
258     {
259         if(0 == msg.acc.sp)
260         {
261             loading();
262             ano_main(msg.acc.account);
263         }
264         else
265         {
266             printf("该账号已在其他客户端登录!\n");
267             sleep(2);
268             return;
269         }
270     }
271     else if(3 <= msg.acc.flag)
272     {
273         printf("账号已被锁定!请先前往解锁!\n");
274         sleep(2);
275         return;
276     }
277     else
278     {
279         printf("登录失败!用户或密码错误!\n");
280         sleep(2);
281         return;
282     }    
283 }
284 
285 //解锁界面
286 void unlock_menu(void)
287 {
288     Msg msg = {3};
289     printf("请输入要解锁的账号:");
290     scanf("%d",&msg.acc.account);
291     //清空缓冲区
292     stdin->_IO_read_ptr = stdin->_IO_read_end;
293     printf("请输入身份证号:");
294     gets(msg.acc.idcard);
295     printf("请输入新密码:");
296     put_pw(msg.acc.password);
297     //将获得的基本信息发送到服务端
298     send(sockfd,&msg,sizeof(Msg),0);
299     //接收服务端传回的信息(账号id)
300     recv(sockfd,&msg,sizeof(Msg),0);
301     if(-1 == msg.acc.flag)
302     {    
303         printf("输入信息不正确或该账户不需要解锁!\n");
304         sleep(2);
305         return;
306     }
307     printf("解锁成功!\n");
308     printf("*****您的id是%d,新密码为%s*****\n",msg.acc.account,msg.acc.password);
309     sleep(2);
310     return;    
311 }
312 
313 //销户界面
314 void delete_menu(void)
315 {
316     Msg msg = {4};
317     //获取账号密码
318     printf("请输入账号:");
319     scanf("%d",&msg.acc.account);
320     //清空缓冲区
321     stdin->_IO_read_ptr = stdin->_IO_read_end;
322     printf("请输入密码:");
323     put_pw(msg.acc.password);
324     //将获得的基本信息发送到服务端
325     send(sockfd,&msg,sizeof(Msg),0);
326     //接收服务端传回的信息(账号id)
327     recv(sockfd,&msg,sizeof(Msg),0);
328     if(-2 == msg.acc.flag)
329     {
330         printf("销户成功!\n");
331         sleep(2);
332     }
333     else
334     {
335         printf("销户失败!\n");
336         sleep(2);
337     }
338     return;
339 }
340 int main()
341 {
342     // 创建socket对象
343     sockfd = socket(AF_INET,SOCK_STREAM,0);
344     if(0 > sockfd)
345     {
346         perror("socket");
347         return -1;
348     }
349     // 准备通信地址
350     struct sockaddr_in addr = {};
351     addr.sin_family = AF_INET;
352     addr.sin_port = htons(1904);
353     addr.sin_addr.s_addr = inet_addr("192.168.1.110");
354     // 连接
355     if(0 > connect(sockfd,(struct sockaddr*)&addr,sizeof(addr)))
356     {
357         perror("connect");
358         return -1;
359     }
360     
361     while(1)
362     {
363         system("clear");
364         show_menu();
365         switch(getch())
366         {
367             case 49:open_menu();break;
368             case 50:login_menu();break;
369             //case 51:unlock_menu();break;
370             //case 52:delete_menu();break;
371             case 53:return 0;
372         }
373     }
374 }

使用的工具函数

 1 #include "customer.h"
 2 
 3 //创建消息队列
 4 int create_msg_queue(int keynum)
 5 {
 6     //获取ipc键值
 7     key_t key = ftok("~",keynum);
 8     //创建消息队列
 9     int msgid = msgget(key,IPC_CREAT|0644);
10     if(0 > msgid)
11     {
12         perror("msgget");
13         return -1;
14     }
15     
16     return msgid;
17 }
18 
19 //隐藏密码输入
20 char* put_pw(char* pw)
21 {
22     for(int i=0; i<20; i++)
23     {
24         stdin->_IO_read_ptr=stdin->_IO_read_end;
25         pw[i]=getch();
26         if(pw[i] == 127)
27         {
28             if(i>0)
29             {
30                 i -= 2;
31                 printf("\b \b");
32             }
33             else
34             {
35                 i--;
36             }
37         }
38         else if(pw[i] == 10)
39         {
40             pw[i]='\0';
41             break;
42         }
43         else
44         {
45             putchar('*');
46         }
47     }
48     return pw;
49 }

定义的头文件

 1 #ifndef CUSTOMER_H
 2 #define CUSTOMER_H
 3 
 4 #include <stdio.h>
 5 #include <sys/types.h>
 6 #include <sys/ipc.h>
 7 #include <sys/msg.h>
 8 #include <string.h>
 9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <fcntl.h>
12 #include <sys/wait.h>
13 #include <getch.h>
14 #include <stdbool.h>
15 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
18 #include <pthread.h>
19 #include <semaphore.h>
20 #include <signal.h>
21 
22 #define key1 123456
23 #define key2 654321
24 typedef struct Account
25 {
26     int account;
27     int target;
28     char name[20];
29     char password[10];
30     char idcard[18];
31     float money;
32     int flag;
33     int sp;
34 }Account;
35 typedef struct Msg
36 {
37     long type;
38     Account acc;
39 }Msg;
40 
41 int create_msg_queue(int keynum);
42 char* put_pw(char* pw);
43 
44 #endif

Makefile

 1 all: 2 gcc -std=gnu99 -c customer.c 3 gcc -std=gnu99 -c tools.c 4 gcc customer.o tools.o -o customer -lpthread 

转载于:https://www.cnblogs.com/kid971220/p/10497801.html

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

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

相关文章

为什么航空发动机那么难造?看看3D工作原理

来源&#xff1a;网络目前大部分航空发动机都是属于燃气涡轮型&#xff0c;民用客机的发动机突出的安全性和可靠性&#xff0c;而军用发动机在这个基础上还追求更大的推力&#xff0c;以及开加力时的最大推力。由此可见&#xff0c;航空发动机领域中最强者必然是军用航发&#…

OSGB格式解析

主要介绍倾斜摄影数据OSGB二进制数据的解析&#xff0c;首先简单介绍一下OpenSceneGraph相关技术&#xff0c;并介绍倾斜摄影数据的组织结构&#xff0c;着重分析OSGB格式的相关字段&#xff0c;最后逐字节对OSGB数据进行解析并通过OpenSceneGraph对数据进行可视化&#xff0c;…

《动手学深度学习》 第二天 (自动求梯度)

2.3、自动求梯度 MXNet提供的autograd模块可以用来自动求梯度。 2.3.1 一个简单的栗子 这里我们要求对函数 y 2xTx &#xff08;2乘以x的转秩乘以X&#xff09;求关于列向量 x 的梯度。(使用jupyter notebook) 1、 创建变量x,并赋初值 x nd.arange(4).reshape((4,1)) #…

JS DOM节点增删改查 属性设置

一.节点操作增createElement(name)创建元素 appendChild();将元素添加 删获得要删除的元素 获得它的父元素 使用removeChild()方法删除 改第一种方式:使用上面增和删结合完成修改第二中方式:使用setAttribute();方法修改属性 使用innerHTML属性修改元素的内容 查<s…

CMake基本用法与项目编译

1.简介 1.1 CMake编译项目主要是 通过编写CMakeList.txt文件项目的每个子文件夹下分别编写CMakeList.txt&#xff0c;通过CMake工具来根据CMakeList文件生成makefile&#xff0c;最后编译成可执行文件。 1.2 通过CMake可以编译不同版本的vs项目&#xff0c;方便在不同版本的vs…

《动手学深度学习》 第二天 (线性回归)

3.2 线性回归的从零开始实现 只利用NDArray和autograd来实现一个线性回归的训练。 首先&#xff0c;导入本节中实验所需的包或模块&#xff0c;其中的matplotlib包可用于作图&#xff0c;且设置成嵌入显示。 %matplotlib inline from IPython import display from matplotli…

Gartner发布2021年新兴技术成熟度曲线

来源&#xff1a;Gartner中国8月24日&#xff0c;Gartner 公司最新发布了“2021年新兴技术成熟度曲线”&#xff08;Hype Cycle for Emerging Technologies&#xff0c;2021&#xff09;。其中&#xff0c;建立信任&#xff0c;加速增长以及塑造变革将是三大主要趋势&#xff0…

Vue语法学习第一课——插值

学习关于Vue的插值语法 ① 文本值 &#xff1a; "Mustache"语法&#xff0c;即双大括号 1 <span>Message:{{msg}}</span> 注&#xff1a;双大括号中的msg值改变&#xff0c;插入的内容也会随之改变&#xff0c;可通过v-once指令限制&#xff0c;但会影响…

计算方法之方程求根、线性方程组求解、插值方法、数值积分简介

提示:本文章主要通过介绍方程求根、线性方程组求解、插值方法、数值积分等相关方法的理论知识,并运用相关方法来解决一个实际的问题,文章中简单介绍了二分法、不动点迭代,牛顿法、Scant Method等方程求根方法,Gauss-Seidel迭代,Jacobi迭代,SOR迭代,Gauss消元法等方程组…

hadoop 重新格式化 NameNode

【问题描述】 在安装配置hadoop的过程中&#xff0c;很可能发生错误导致datanode或者namenode 启动失败&#xff0c;这时我们可以选择重新格式化 namenode。 一、删除data数据和log日志 二 、使用命令 bin/dfs namenode -format 重新格式化 【注意事项】 为什么不能一直格式…

人工智能“上位”会让程序员消失吗?

大脑以及二进制代码&#xff08;图&#xff1a;Canva&#xff09;来源&#xff1a;Forbes作者&#xff1a;Nisha Talagala编译整理&#xff1a;科技行者写代码已经成了许多工作的一项关键技能。一些国家和学校甚至认为&#xff0c;编程语言是一种可以接受的外语。而在各种熙熙攘…

分类的IP地址

现有物理地址再有IP地址IP地址的表示方法为点分十进制法IP地址的设计思想&#xff1a;网络部分 主机部分 分类的IP地址 特征&#xff1a;根据不同特征的IP地址&#xff0c;事先约定好网络号所占的位数和主机号所占的位数。 A类地址 全球一共有27-2 个A类网络&#xff0c;每…

人工智能之深度优先,广度优先,贪婪最佳优先搜索,A*搜索以及爬山法与遗传算法

项目场景: 1. 分别用宽度优先、深度优先、贪婪算法和A*算法求解“罗马利亚度假问题”。 2. 分别用爬山法和GA算法求解n皇后问题。 文章目录 项目场景:一、度假场景1.1 问题描述2.1 问题分析:1.3 解决方案:1.4 运行结果二、N皇后问题2.1 问题描述2.2 数据存储结构2.3 算法思…

操作系统之多级队列调度算法,银行家算法,动态分区式存储区管理

题目描述: 1.对于多级队列调度算法,主要介绍轮转法,短进程优先算法;银行家算法主要介绍进程的资源分配策略; 2.对于动态分区式存储区管理,主要介绍首先适应法,最佳适应法,最坏适应法等调度算法。 文章目录 题目描述:程序功能及设计思路1. 多级队列调度算法函数设计2. …

卫星对于物联网来说是一个非常好的选择

ALAMY来源&#xff1a;IEEE电气电子工程师对许多人来说&#xff0c;“物联网”一词可能会让人想起智能城市的努力&#xff0c;比如配备交通摄像头和空气质量传感器的路灯&#xff0c;或者在自己家里连接设备。一个很自然的问题是&#xff0c;为什么你从没想使用卫星连接任何这些…

利用子网掩码划分子网

分类IP地址的弊端 一个物理网络不能过大&#xff0c;否则网络性能很差&#xff0c;某个B类或A类IP网络无法全部用于单个物理网络分类IP地址分配不合理&#xff0c;利用率低分类IP地址设计的弊端 —— 不灵活&#xff0c;IP地址利用率不高 划分子网的思路 网络管理员将本应属于…

springcloud流程图

自己画的&#xff1a; 别人画的 别人画的2 转载于:https://www.cnblogs.com/dzhou/p/10504215.html

编译原理之LR语法分析器,自动机

本博客主要介绍LR语法分析器的代码实现,包含完整的测试数据与源代码。 文章目录 1. 主要内容:2.实验过程2.1 实验数据2.2 源代码1. 主要内容: LR语法分析器理论:https://blog.csdn.net/qq_40294512/article/details/92621241 2.实验过程 2.1 实验数据 G.txt数据文件 E-&…

java 搭建 web服务器 socket实现

【写在前面】 云计算的第n个java作业&#xff0c;开始一直不懂为什么老师一直让我们写java web的小demo&#xff0c;不应该是hadoop啥的直接上框架嘛。后来慢慢了解到&#xff0c;其实java web 的一些内容确实是云计算的基础。这个demo是用java socket 来搭建一个web服务器&…

【趋势】未来十年计算机体系结构的历史和趋势

来源&#xff1a;机器之心先分享我对这篇文章的总结&#xff0c;或者我得到的启发&#xff1a;1、DSA&#xff08;Domain-Specific Architectures&#xff0c;特定领域的体系结构&#xff09;将成为未来十年甚至更长时间&#xff0c;计算机体系结构的趋势。登纳德缩放定律结束、…