首先,要完成通信至少要建2个工程,分别为服务端与客户端,这两个工程的环境配置与头文件添加都要按以下步骤进行
?一、环境配置
先说mysql环境配置。
右键项目名称,找到属性。

?配置属性->调试->环境:将mysql\mysql server \bin 的路径复制,写PATH=路径

?其中,如果没有自己定义,那么mysql文件夹一般在C:\program Fiels中。

而后,仍然在属性栏中的C/C++中选择常规,将mysql server 中的include文件夹的路径编辑进附加包含目录中去。别忘了加英文的分号:

接着选择链接器,如下图将lib文件夹的路径编辑进去:

接着选择链接器的输入,点击附加依赖项,选择右边的小箭头,编辑,然后输入: libmysql.lib,选择确定:

然后为代码添加头文件<mysql>。编译后如果报错,则进行以下操作:
进入mysql server的lib文件夹,复制libmysql.dll文件,而后打开项目文件夹,返回上一级。
将该文件复制进x64的debug文件夹内。


?

??
至此,配置结束,如果仍报错可以适当更改libmysql.dll的位置。
二、mysql笔记
?这份笔记我是看黑马程序员的视频总结的。由于实训使用mysql的消息突然,我的mysql只学了2天,不过也算勉强会使用。而mysql与c++的联动则是花费了我很大很大功夫,查了巨量资料,问了很多人才勉强入门,了解到曾经未曾听闻也无从下手的函数。下面是我整理出的极其、极其干货的一分笔记,查询mysql语法以及mysql与c++联动的函数时很方便。我先放两张截图告诉大家重点:
1:mysql语句在哪查:

?从“纯sql语句”向下便是mysql语句干货,查起来非常方便,向上则是mysql的基本数据类型。学习前大致看看,有印象即可。
2.c++中的mysql函数在哪查:

从此处向下便是。后面还有一些socket的语法,不过我没有细心总结 ,大家可以不看。
MYSQL注释:
MySQL 单行注释
1) 单行注释可以使用#注释符,#注释符后直接加注释内容。格式如下:
#注释内容
2) 单行注释可以使用--注释符,--注释符后需要加一个空格,注释才能生效。格式如下:
-- 注释内容
#和--的区别就是:#后面直接加注释内容,而--的第 2 个破折号后需要跟一个空格符在加注释内容。
MySQL 多行注释
多行注释使用/* */注释符。/*用于注释内容的开头,*/用于注释内容的结尾。多行注释格式如下:
/*
第一行注释内容
第二行注释内容
*/
MYSQL数据类型:
整数类型 字节 有符号取值范围 无符号取值范围
TINYINT 1 -128~127 0~255
SMALLINT 2 -32768~32767 0~65535
MEDIUMINT 3 -8388608~8388607 0~16777215
INT 4 -2147483648~2147483647 0~4294967295
BIGINT 8 -9223372036854775808~9223372036854775807 0~18446744073709551615
整数类型的可选属性有三个:
(M)
表示最低显示宽度,例如int(5),当数据宽度小于5位时在数字前面需要用字符填满宽度。该项功能要配合”ZEROFILL“使用,否则指定宽度无效。
如果设置了显示宽度,不会对插入的数据有影响,还是按照类型的实际宽度保存。从MySQL8.0.17开始,整数数据类型不推荐使用显示宽度属性。
UNSIGNED
表示无符号类型。使用:INT UNSIGNED
ZEROFILL
表示0填充。如果某列是ZEROFILL,那么mysql会自动为当前列添加UNSIGNED属性。
如果指定了ZEROFILL表示不够M位时,用0在左边填充,超过M位时,只要不超过数据存储范围即可。
(M)必须和UNSIGNED ZEROFILL一起使用才有意义,M的值跟int所占多少存储空间没有关系,int(3),int(4)在磁盘上都是占用4个字节。
字符串类型 字节 描述及存储需求
CHAR(M) M M为0~255之间的整数
VARCHAR(M) M为0~65536之间的整数
TINYBLOB 允许长度0~255字节
BLOB 允许长度0~65535字节
MEDUIMBLOB 允许长度0~167772150字节
LONGBLOB 允许长度0~4294967295
TINYTEXT 允许长度0~255字节
TEXT 允许长度0~65535字节
MEDIUMTEXT 允许长度0~167772150字节
LONGTEXT 允许长度0~4294967295字节
VARBINARY(M) M 允许长度0~M个字节的边长字节字符集
BINARY(M) M 允许长度0~M个字节的定长字节字符集
CHAR与VARCHAR类型
CHAR和VARCHAR很类似,都是用来保存Mysql中较短的字符串,主要区别在于:CHAR列的长度固定为创建表时声明的长度,长度可以为从
0~255的任何值,而VARCHAR的值可以是变长字符串,长度可以指定0~65535之间的值,在检索的时候,CHAR列会删除尾部的空格而
VARCHAR则保留了这些空格。
ENUM类型
枚举类型,它的值范围需要在创建表时通过枚举方式显示指定,对1~255个成员的枚举需要1个字节存储,对于255~65535个成员,需要2
个字节存储,最多允许65535个成员。
SET类型
SET和enum非常相似,里面可以包含0~64个成员,根据成员的不同,存储上也有不同。
1~8成员的集合,占1个字节
9~16成员的集合,占2个字节
17~24成员的集合,占3个字节
25~32成员的集合,占4个字节
33~64成员的集合,占8个字节
set类型一次可以选取多个成员,而ENUM则只能选一个,就相当于ENUM是单选,而set是复选。
浮点类型 占用空间 精度 精确性
FLOAT 4 单精度 精确到小数点后7位小数
DOUBLE 8 双精度 精确到小数点后15位小数
DECIMAL 变长 高精度 精确到小数点后65位小数
数据精度说明
对于浮点数类型,在MySQL中单精度使用4个字节,双精度使用8个字节。
MySQL允许使用非标准语法(其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么用):FLOAT(M,D) , DOUBLE(M,D),M称为精
度(整数+小数),D称为标度(小数)。D<M<=255,0<=D<=30。例如:定义FLOAT(5,2)的一个列可以显示-999.99~999-99,超出这个范围
会报错。FLOAT和DOUBLE类型在不知道(M,D)时,默认按照实际的精度(由实际硬件和操作系统决定)来显示。不管是否显示设置了精度(M,D)
,MySQL的处理方案如下:如果存储时,整数部分超出范围,MySQL就会报错,不允许存这样的值。如果存储时,小数点部分超出范围,则:若四
舍五入后,整数部分没有超出范围,则只是警告,但能成功操作并且四舍五入删除多余的小数位后保存。例如FLOAT(5,2)插入999.009,近似
结果是999.01;若四舍五入后,整数部分超出范围,则报错;
定点类型 字节数 含义
DECIMAL(M,D),DEC,NUMERIC M+2字节 有效范围由M和D决定
使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=65,0<=D<=30,D<M。例如,定义DECIMAL(5,2)
的类型,表示该列取值范围是-999.99~999.99。DECIMAL(M,D)的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的。
DECIMAL 的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节。也就是说,在一些对精度要求不高的场景下,比起占用
同样字节长度的定点数,浮点数表达的数值范围可以更大一些。定点数在MySQL内部是以字符串的形式进行存储,这就决定了它一定是精准的。当
DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0),表示有10个整数位,0个小数位,其范围:-9999999999~9999999999。当数
据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。
二进制字符串类型 长度 长度范围 占用空间
BIT(M) M 1<=M<=64 约为(M+7)/8字节
如果没有指定M,默认是1位。如果插入的是10进制的,会转为二进制插入。
在使用select命令查询字段时,可以使用bin()或hex()函数进行读取。
日期时间类型 名称 字节 日期格式 最小值 最大值
YEAR 年 1 YYYY或YY 1901 2155
TIME 时间 3 HH:MM:SS -838:59:59 838:59:59
DATE 日期 3 YYYY-MM-DD 1000-01-01 9999-12-03
DATETIME 日期时间 8 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 9999-12-31 23:59:59
TIMESTAMP 日期时间 4 YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:00UTC 2038-01-19 03:14:07UTC
时间类型 TIME 的取值范围不是 -23:59:59~23:59:59 的原因是 MySQL 设计的 TIME 类型,不光表示一天之内的时间,而且可以
用来表示一个时间间隔,这个时间间隔可以超过 24 小时。
关于 `
` 是 MySQL 的转义符,避免和 mysql 的本身的关键字冲突,只要你不在列名、表名中使用 mysql 的保留字或中文,就不需要转义。
所有的数据库都有类似的设置,不过mysql用的是`而已。通常用来说明其中的内容是数据库名、表名、字段名,不是关键字。例如:
select from from table;
第一个from是字段名,最后的table表名,但是同时也是mysql关键字,这样执行的时候就会报错,所以应该使用
select `from` from `table`;
当然,为了便于阅读,不建议使用关键字作为字段名、表名,同时,应该对数据库名、表名、字段名用一对儿反引号包含。
[]内表示可不写的内容,[]在编译时不用写
不区分大小写
纯SQL语句:
DDL:
查询所有数据库: SHOW DATABASES;
查询当前数据库: SELECT DATABASE();
创建数据库: CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则];
删除数据库: DROP DATABASE [IF EXISTS] 数据库名;
使用数据库: USE 数据库名;
查询当前正在使用的数据库中的所有表: SHOW TABLES;
查询表结构: DESC 表名;
创建表: CREATE TABLE 表名(
字段1 字段1类型 [COMMENT 字段1注释],
...
字段n 字段n类型 [COMMENT 字段n注释]//最后一行无逗号
)[COMMENT 表注释];
向表中添加字段(列): ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
修改字段(列):
修改数据类型:ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
修改字段名和类型:ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [COMMENT 注释] [约束];
删除字段:ALTER TABLE 表名 DROP 字段名;
修改表名:ALTER TABLE 表名 RENAME ID 新表名;
删除表:DROP TABLE [IF EXISTS] 表名;
删除并重新创建表:TRUNCATE TABLE 表名;
DML:
给指定字段添加数据:INSERT INTO 表名(字段名1,字段名2...) VALUES (值1,值2...);
给全部字段添加数据:INSERT INTO 表名 VALUES(值1,值2...);
批量添加数据:INSERT INTO 表名(字段名1,字段名2...) VALUES (值1,值2...),(值1,值2...)...;
INSERT INTO 表名 VALUES (值1,值2...),(值1,值2...)...;
修改数据:UPDATE 表名 SET 字段名1=值1,字段名2=值2,...[WHERE 条件];
注意:如果没有条件,代表要修改该表选中字段名下的所有数据
删除数据:DELETE FROM 表名 [WHERE 条件];
* 字段列表 即:字段名1,字段名2...
DQL:
查询多字段:SELECT 字段1,字段2... FROM 表名;
查询全部字段(不推荐这样写):SELECT * FROM 表名;
设置别名:SELECT 字段1 [AS 别名1],字段2 [AS 别名2]...FROM 表名;
去除重复记录:SELECT DISTINCT 字段列表 FROM 表名;
条件查询:
SELECT 字段列表 FROM 表名 WHERE 条件列表;
MYSQL条件类型:
比较运算符 逻辑运算符 模糊匹配 like
等于 = and 或 && %表示任意多个任意字符
大于 > or 或 || _表示一个任意字符
大于等于 >= not 或 !
小于 <
小于等于 <=
不等于 != 或 <>
范围 BETWEEN...AND... 左小于右
列表多选一 IN(...)
范围查询 空值查询
in表示在一个非连续的范围内 is null
not in表示不在一个非连续的范围内 is not null
查询没有学号的学生:
SELECT * FROM 表名 WHERE 字段名 IS NULL;
查询长度为2的字符:
select 字段列表 from 表名 where 字段名 like'__';
查询名字以汽车车结尾的产品
select 字段列表 from 表名 where name like '%汽车';
查询姓商的同学:
select 字段列表 from 表名 where name like '商%';
特殊的范围查询:
select 字段列表 from 表名 where 字段名 between 值1 and 值2;
值1必须小于等于值2
select 字段列表 from 表名 where 字段名 in(值1,值2...);
多个条件之间用逻辑运算符链接
聚合函数:
常见聚合函数:
count 统计数量 max 最大值
min 最小值 avg 平均值
sum 求和
求表中的数据数量:SELECT COUTN(*) FROM 表名;
求表中某字段的数据数量:SELECT COUNT(数据名) FROM 表名;
求表中某字段的平均值:SELECT AVG(字段名) FROM 表名;
求表中某字段的最大值:SELECT MAX(字段名) FROM 表名;
求所有名字叫'阿白'的学生的最小身高:SELECT MIN(height) FROM student where name = '阿白';
分组查询:
SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
注意:where 与 having 的区别
where 分组前过滤,不满足where条件的不参与分组
having 分组后过滤,对分组结果进行过滤
查询男女人数:select gender, count(*) from emp grop by gender;
显示如下:
gender `count(*)`
女 女生人数
男 男生人数
查询年龄<45岁的员工,并根据工作地址分组,获取员工数量大于等于3的工作地址
select workaddress as 工作地址, count(*) as 人数 from employee where age < 45 group by 工作地址 having 人数 >= 3;
执行顺序:where > 聚合函数 > having
排序查询:
SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2...;
排序方式:
升序(默认值):ASC
降序:DESC
根据年龄对公司的员工升序排序:
SELECT * FROM employee order by age;
根据入职时间降序排序:
select * from employee order by entryDate desc;
先按年龄升序排序,年龄相同按照入职时间降序排序:
select * from employee order by age, entryDate desc;
分页查询:
select 字段列表 from 表名 limit 起始索引,查询记录数;
起始索引从0开始,起始索引 = (查询页码 - 1) * 每页显示的记录数
如果查询的是第一页的数据,起始索引可省略
例:
查询第一页员工数据,每页显示10条记录:
select * from empployee limit 0,10;
查询第二页员工数据,每页显示10条记录:
select * from empployee limit 10,10;
查询第三页前八条员工记录,每页显示10条数据
select * from employee limit 20,8;
DQL编写顺序:
select 字段列表 from 表名 where 条件列表 group by 分组字段列表
having 分组后条件列表 order by 排序字段列表 limit 分页参数
DQL执行顺序:
from->where->group by->having->select->order by->limit
别名的特殊使用:
select e.name , e.age from employee e where e.age > 15;
DCL:
查询用户:
USE mysql;
select * from user;
创建用户:
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
修改用户密码:
ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
删除用户
DROP USER '用户名'@'主机名';
例:
创建用户 ab, 只能在当前主机(localhost)访问,密码为aaa;
create user 'ab'@'localhost' identified by 'aaa';
创建用户 cd, 可以在任意主机访问,密码为bbb;
create user 'cd'@'%', identified by 'bbb';
修改 ab 的密码为'ccc';
alter user 'ab'@'localhost' idetified with mysql_native_password by 'ccc';
加密方式↑
权限控制:
查询权限:SHOW GRANTS FOR '用户名'@'主机名';
授予权限:GRANT 权限列表 ON 数据库名,表名 TO '用户名'@'主机名';
撤销权限:REVOKE 权限列表 ON 数据库名,表名 FROM '用户名'@'主机名';
例:
grant all on employee.* to 'cd'@'%';
revoke all on employee.* from 'cd'@'%';
grant all *.* to 'ab'@'localhost';
函数
字符串函数:
concat(s1,s2...sn)
将字符串s1~sn拼接为一个字符串
lower(str)
转小写
upper(str)
转大写
lpad(str,n,pad)
左填充,用字符串pad填充str到长度n
rpad(str,n,pad)
右填充,用字符串pad填充str到长度n
trim(str)
去掉字符串头部和尾部的空格
substring(str,start,len)
返回str从start起长度len的字符串,索引从1开始
例:
select concat('hello', 'mysql');
select lower('HEllo');
select lpad('01',5,'-');
select rpad('01',6,'a3b');
update employee set worknumber = lpad(worknumber,5,'0');
...
数值函数:
celi(x) 对x向上取整
floor(x) 对x向下取整
mod(x,y) 返回 x%y
rand() 返回0~1内的随机数
round(x,y) 求参数x的四舍五入的值,保留y位小数
例:
生成六位验证码
select lpad(round(rand()*1000000, 0), 6, '0');
日期函数:
curdate() 返回当前日期
curtime() 返回当前时间
now() 返回当前日期和时间
year(date) 获取指定date的年份
month(date) 获取指定date的月份
day(date) 获取指定date的日期
date_add(date, interval expr type)
返回一个日期/时间值加上一个时间间隔expr后的时间值
datediff(date1,date2) 返回起止时间之间的天数
例:
select date_add(now(), interval 70 month);
select datediff('2021-10-01','2022-12-15');
...(可嵌套)
流程控制函数:
if(value, t, f)
如果value为true,返回t,否则返回f
ifnull(value1, value2)
如果value1不为空,返回value1,否则返回value2
case when [val1] then [res1] ... else [default] end
如果val1为true,返回res1,...否则返回default默认值
case [expr] when [val1] then [res1]...else [default] end;
如果expr的值等于val1,返回res1,...否则返回default默认值
例:
select ifnull('', 'default'); 返回''
select ifnull(null, 'default'); 返回default
select
id,
name,
(case when math >= 85 then '优秀' when math >= 60 then '及格' else '不及格' end) '数学';
from score;
select
name,
(case workaddress when '北京' then '一线' when '上海' then '一线' else '二线' end) as '工作地址'
from employee;
约束
关键字 约束名 效果
not null 非空约束 限制该字段数据不能为null
unique 唯一约束 保证该字段所有数据都唯一,不重复
primary key 主键约束 主键是一行数据的唯一标识,非空且唯一
default 默认约束 保存数据时,如果未指定该字段的值,则采用默认值
check 检查约束 保证字段值满足某一个条件
foreign key 外键约束 用来让两张表的数据之间建立连接,保证数据的一致性和完整性
外键行为 说明
no action 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新
restrict 与no action一致
cascade 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在字表中的记录
set null 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键的值为null(要求外键允许取null)
set default 父表有变更时,子表将外键列设置为一个默认的值
添加外键:
创建表时:
create table 表名(
字段名 数据类型...
...
[constraint][外键名称] foreign key (外键字段名) references 主表(主表列名)
)...;
创建表后:
alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(主表列名);
删除外键:
alter table 表名 drop foreign key 外键名称;
设置外键行为:
添加外键的语法 on update 更新时的行为 on delete 删除时的行为
例:
create table user( 自动增长↓
id int primary key auto_increment comment '主键',
name varchar(10) not null unique comment '姓名',
age int check ( age > 0 && age < 120 ) comment '年龄',
status char(1) default '1' comment '状态',
gender char(1) comment '性别'
dept_id int comment '外键约束' #之后用来链接外键
)comment '用户表';
alter table employee add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
alter table employee drop foreign key fk_emp_dept_id;
多表查询
查看多表关系:在DG中,右键中间表,最下面选择以可视化界面展示
一对多:多的一方的外键链接一的一方的主键
多对多:建立中间表并建立两个外键,分别链接另外两表的主键
一对一(多用于拆分的表):任意一方加入外键,关联另外一方的主键,并设置外键为唯一(unique)
有效查询多个有关的表:
select * from emp, dept where emp.dept_id = dept.id;
内连接:查询A,B交集的数据
隐式内连接:select 字段列表 from 表1,表2 where 条件...
显式内连接:select 字段列表 from 表1[inner] join 表2 on 连接条件...
c++中的MYSQL
所需头文件
#include <WinSock2.h>
? ? #include <mysql.h>
#pragma comment(lib,"libmysql.lib")
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib, "ws2_32.lib")
一般将执行语句封入string,再通过.c_str()传入相应函数
MYSQL* mysql = NULL 创建数据库对象
mysql_init() 初始化数据库
mysql_options() 连接设置
mysql_real_connect() 连接数据库
mysql_query() 传入指令
mysql_store_result() 获得数据库结果集
mysql_num_rows() 获得结果集中的行数
mysql_num_fields() 获得结果集中的列数
mysql_fetch_field() 获取列的字段名、字段类型和大小等信息
mysql_fetch_row() 检索结果集的下一行
mysql_free_result() 释放先前查询所储存的数据集
mysql_close() 关闭当前数据库链接
errorIntoMySQL() 弹出错误
mysql_store_result()与 mysql_use_result():
mysql_store_result()立即检索所有的行,而 mysql_use_result()启动查询,但实际上并未获取任何行,
mysql_store_result()假设随后会调用 mysql_fetch_row()检索记录。这些行检索的不同方法引起两者在其
他方面的不同。本节加以比较,以便了解如何选择最适合应用程序的方法。当mysql_store_result()从服务器
上检索结果集时,就提取了行,并为之分配内存,存储到客户机中,随后调用 mysql_fetch_row()就再也不会返
回错误,因为它仅仅是把行脱离了已经保留结果集的数据结构。mysql_fetch_row()返回 NULL始终表示已经到达
结果集的末端。相反,mysql_use_result()本身不检索任何行,而只是启动一个逐行的检索,就是说必须对每行
调用 mysql_fetch_row()来自己完成。既然如此,虽然正常情况下,mysql_fetch_row()返回NULL仍然表示此
时已到达结果集的末端,但也可能表示在与服务器通信时发生错误。可通过调用mysql_errno()和mysql_error()
将两者区分开来。与mysql_use_result()相比,mysql_store_result()有着较高的内存和处理需求,因为是
在客户机上维护整个结果集,所以内存分配和创建数据结构的耗费是非常巨大的,要冒着溢出内存的危险来检索大型
结果集,如果想一次检索多个行,可用 mysql_use_result()。mysql_use_result()有着较低的内存需求,因为
只需给每次处理的单行分配足够的空间。这样速度就较快,因为不必为结果集建立复杂的数据结构。另一方面,
mysql_use_result()把较大的负载加到了服务器上,它必须保留结果集中的行,直到客户机看起来适合检索所有的
行。这就使某些类型的客户机程序不适用mysql_use_result():
c++中的TCP
WSAData wsaData: 存放windows socket初始化信息
WSAStartup: 使库文件与当前的应用程序绑定,以调用该版本的socket的各种函数
原型:int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
参数:wVersionRequested是Windows Sockets API提供的调用方可使用的最高版本号。高位字节指出
副版本(修正)号,低位字节指明主版本号。lpWSAData 是指向WSADATA数据结构的指针,用来接收
Windows Sockets实现的细节。
返回值:返回0则执行成功。
word类型:储存socket编程中的版本信息
makeword():创建word类型。
LOBYTE(): 取 16 进制数的最低字节
HIBYTE(): 取 16 进制数的最高字节
//这俩的返回值不用管,照着写就行,没查到,老师说是默认(
WSACleanup(): 清理,成功返回0,可用WSAGetLastError来获取错误码。
注意:
当调用了WSACleanup,在此进程中任何挂起的或者异步的套接字调用都会取消,而且不会发出通知消息也不会设置事件对象。
为了使挂起的数据发送出去,应用程序应该使用shutdown来关闭连接,然后一直等待关闭完成再调用closesocket和WSACleanup。
和WSAStartup一样,WSACleanup也不能在DllMain中调用(可能会死锁)。
SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0):
建立一个协议族为AF_INET、协议类型SOCK_STREAM、协议编号为0的套接字
AF_UNIX(本机通信)
AF_INET(TCP/IP – IPv4)
AF_INET6(TCP/IP – IPv6)
SOCK_STREAM(TCP流)
SOCK_DGRAM(UDP数据报)
SOCK_RAW(原始套接字)
INVALID_SOCKET: 表示该 socket fd 无效。(判断正误)
sockaddr_in:internet环境下套接字的地址形式
htonl:把本机字节顺序转化为网络字节顺序
h:host 本地主机
to:to
n:net 网络的意思
l:unsigned long
INADDR_ANY:监听0.0.0.0地址
bind():给socket绑定端口号与具体位置
参数 1:需要绑定的socket。
?? 参数 2:存放了服务端用于通信的地址和端口。
?? 参数3:表示 addr 结构体的大小
?? 返回值:成功则返回0 ,失败返回-1,错误原因存于 errno 中。如果绑定的
地址错误,或者端口已被占用,bind 函数一定会报错,否则一般不会返回错误。
sockaddr:一种通用的套接字地址
CONNECT_NUM_MAX:(没搜到这个宏)
sockaddr_in:internet环境下套接字的地址形式
accept():接收一个套接字中已建立的连接
参数1:利用系统调用socket()建立的套接字描述符,通过bind()绑定到一个本地地址(一般为服务器的套接字),并且通过listen()一直在监听连接;
参数2:指向struct sockaddr的指针,该结构用通讯层服务器对等套接字的地址(一般为客户端地址)填写,返回地址addr的确切格式由套接字的地址
类别(比如TCP或UDP)决定;若addr为NULL,没有有效地址填写,这种情况下,addrlen也不使用,应该置为NULL;
参数3:一个值结果参数,调用函数必须初始化为包含addr所指向结构大小的数值,函数返回时包含对等地址(一般为服务器地址)的实际数值;
recv(): 从连接的套接字或绑定的无连接套接字接收数据
参数1:指定接收端套接字描述符;
参数2:指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
参数3:指明buf的长度;
参数4:一般置0。
返回值:<0 出错; =0 连接关闭; >0 接收到数据大小
send():将我们的数据复制黏贴进系统的协议发送缓冲区,计算机伺机发送出去
参数1:标识已连接套接字的描述符。
参数2:指向包含要传输的数据的缓冲区的指针。
参数3:buf参数指向的缓冲区中数据的长度(以字节为单位)。
参数4:一组标志,指定进行呼叫的方式。 通过将按位或运算符与以下任何值一起使用来构造此参数。
返回值:成功返回写入的字节数;执行失败,返回SOCKET_ERROR
closesocket():关闭一个套接口
三、头文件添加
下面是代码。代码分为三部分 服务端,客户端,还有一个我自己定义的stdafx头文件。这个头文件是vs库自带的。我的出于某些原因没有。当然,如果你有的话,将stdafx头文件放在最上方,下方添加以下头文件:
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <mysql.h>
#pragma comment(lib,"libmysql.lib")
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include <ctime>
#include <random>
#include <sstream>
#include<Windows.h>
如果不知道头文件如何创建:

?
刚创好的头文件会自带一行#pragma once。自定义中写过了,覆盖即可。
自定义的stdafx头文件内容:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#if !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)
#define AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// Insert your headers here
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#define DLLEXPORT __declspec(dllexport)
#define DLLIMPORT __declspec(dllimport)
#include <WinSock2.h>
#include <Ws2tcpip.h>
#include <mysql.h>
#pragma comment(lib,"libmysql.lib")
#pragma comment(lib,"wsock32.lib")
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<set>
#include <ctime>
#include <random>
#include <sstream>
#include<Windows.h>
// TODO: reference additional headers your program requires here
void Msg(char* szFormat, ...);
void dbMsg(char* szFormat, ...);
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)
需要注意的是,这个头文件服务端,客户端两个工程都需要添加
四、服务端与客户端的创建?
先说明很重要的一点。安装好后每个人都设置了自己的mysql账号和密码。在我的代码中我会将他们删去,如果想使用这份代码,那么需要添上自己的。代码具体位置在服务端的1467行左右:

?涂黑的,左边是账号,右边是密码。
?1.服务端的创建:
别忘了自定义头文件stdafx或者按照上面已有stdafx的情况添加我列出的头文件
代码:
#include "stdafx.h"
WSADATA localWsaData;
SOCKET connectSocket;
SOCKET serverSocket;
DWORD WINAPI sends(LPVOID);
DWORD WINAPI receives(LPVOID);
HANDLE hMUTEX;
int sendInf(std::string sendBuff) {
sendBuff += '\0';
if (sendBuff == "#") {
sendBuff = "system: 服务器端请求终止对话...\n";
closesocket(serverSocket);
WSACleanup();
return 0;
}
if (send(connectSocket, sendBuff.c_str(), sizeof(char) * sendBuff.size(), 0) == SOCKET_ERROR) {
std::cout << "system: 发送连接消息失败: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return -1;
}
return 1;
}
std::string receiveInf() {
char recvBuff[3000]{};
if (recv(connectSocket, recvBuff, 3000, 0) == SOCKET_ERROR) {
std::cout << "system: 接收连接消息失败: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return "";
}
return recvBuff;
}
//便捷读取
class SafeRead
{
public:
//录入数字
static std::string readNum(int length, const std::string& oldNum) {
std::string inf;
//label位置
label:while (true) {
std::cout << " 请输入数字:";
getline(std::cin, inf);
if (inf == "\n" || inf.empty()) {
return oldNum;
}
else if ((int)inf.length() > length) {
std::cout << "\n\t长度超过" << length << "位(计算需要包含小数点),请重新输入。\n";
continue;
}
std::stringstream sin(inf);
double d;
char c;
bool flag = true;
if (!(sin >> d))
flag = false;
if (sin >> c)
flag = false;
if (!flag) {
std::cout << "输入的不是一个数字,请重新输入" << std::endl;
continue;
}
break;
}
//删除前导零
std::string::iterator it = inf.begin();
for (unsigned int i = 0; i < inf.length() - 1; i++) {//单0不删,一串0只留一个
if (inf[i] == '-') continue;
if (inf[i] != '0') break;
if (inf[i] == '0' && inf[i + 1] == '.') break;
inf.erase(it);
it++;
}
return inf;
}
//录入有限制的字符串,用于读取基本信息
static std::string readString(int length, std::string old) {
std::string inf;
while (true) {
getline(std::cin, inf);
if (inf == "\n" || inf.empty()) {
return old;
}
else if ((int)inf.length() > length) {
std::cout << "\n\t信息长度超过" << length << ",请重新输入。\n";
continue;
}
return inf;
}
}
//读取文本块,以~~~结束
static std::string readText(int length, std::string old) {
while (true) {
std::string ans;
while (true) {
std::string inf;
getline(std::cin, inf);
if (inf == "~~~") {
break;
}
else {
ans = ans + inf + "\n";
}
}
if (ans.size() > length) {
std::cout << "当前文本长度(包括空格)为 " << ans.size() << ",已超过限定长度 " << length << ",请重新输入..." << std::endl;
continue;
}
return ans;
}
}
};
//double转string函数
std::string lfToStr(double num)
{
std::stringstream ss;
std::string str;
ss << num;
ss >> str;
return str;
}
//string转换为double函数
double strToLf(const std::string& number) {
double lf = 0, lfi = 0, x = 10;
int i = 0, f = 1, times = 1, length = (int)number.length();
while (number[i] < '0' || number[i] > '9') {//跳过可能存在的¥,$ 或 -
i++;
if (number[i] == '-')
f *= -1;
}
//整数位
while (i < length) {
if (number[i] == '.') {
break;
}
lf = lf * 10 + number[i] - '0';
i++;
}
//小数位,++i跳过‘ . ’
while (++i < length) {
lfi += (number[i] - '0') / x;
x *= 10;
}
return times * f * (lf + lfi);
}
//创建不重复的随机数组
std::vector<int> createRandList(int left, int right) {
int length = right - left + 1;
std::default_random_engine start;
std::uniform_int_distribution<int> getRand(left, right);
start.seed(time(0) + right + rand() % 30);
std::set<int> list;
while (list.size() < length) {
list.insert(getRand(start));
}
std::vector<int> randomSunject(list.begin(), list.end());
return randomSunject;
}
MYSQL localMysql;
//mysql c++的使用
class MysqlOperation {
public:
//封装query函数
static bool useQuery(MYSQL* mysql, std::string instruction) {
int res = mysql_query(mysql, instruction.c_str());
if (res) {
std::cout << mysql_error(mysql) << std::endl;
return false;
}
else {
return true;
}
}
//基础的搜索框架,返回处理过的string型结果集
static std::string basicSelect(MYSQL* mysql) {
MYSQL_RES* result = mysql_store_result(mysql);
int column = mysql_num_fields(result);
std::string ans;
MYSQL_ROW row = mysql_fetch_row(result);
while (row) {
for (int i = 0; i < column; i++) {
if (row[i]) {
ans += row[i];
}
else {
ans += "null";
}
if (i < column - 1) {
ans += "\t";
}
}
row = mysql_fetch_row(result);
if (row) {
ans += "\n";
}
}
mysql_free_result(result);
return ans;
}
//连接数据库
static bool ConnectDB(std::string host, std::string user, std::string password, std::string DBname, int port)
{
MYSQL* mysql = mysql_init(&localMysql);//初始化localMysql
if (!mysql) {
std::cout << mysql_error(mysql) << std::endl;
return false;
}
mysql_options(&localMysql, MYSQL_SET_CHARSET_NAME, "GBK");
mysql = mysql_real_connect(&localMysql, host.c_str(), user.c_str(), password.c_str(), DBname.c_str(), port, NULL, 0);
if (mysql == nullptr) {
std::cout << mysql_error(mysql) << std::endl;
return false;
}
std::cout << "连接mysql成功!\n";//连接成功反馈
std::string DBName = "ExaminationSystem";
createDatabase(DBName);
bool res = useQuery(&localMysql, "use ExaminationSystem");
if (res) {
std::cout << "已转到数据库\"ExaminationSystem\"" << std::endl;
}
return res;
}
//创建数据库
static bool createDatabase(std::string& DBName)
{
std::string oper = "create database if not exists " + DBName;
bool res = useQuery(&localMysql, oper);
if (res) {
std::cout << "\"" << DBName << "\"数据库创建成功或已存在" << std::endl;
}
return res;
}
//更改使用的数据库
static bool changeUsingBase(std::string DBName) {
std::string oper = "use " + DBName;
bool res = useQuery(&localMysql, oper);
if (res) {
std::cout << "数据库使用情况已更改,当前使用的数据库为:\"" + DBName + "\"" << std::endl;
}
return res;
}
//查看连接状态
static bool checkIfConnectDB() {
MYSQL* mysql = &localMysql;
int res = mysql_query(mysql, "select database()");
if (res) {
std::cout << mysql_error(mysql) << std::endl;
return false;
}
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW line = mysql_fetch_row(result);
if (!line) {
std::cout << "未连接任何数据库" << std::endl;
return false;
}
else {
std::cout << "数据库连接状态:已连接\n" << "连接的数据库为:" << line[0] << std::endl;
return true;
}
}
//删除数据库
static bool deleteDataBase(std::string DBName) {
for (auto iter = DBName.begin(); iter != DBName.end(); iter++) {//去除空格
if (isblank(*iter) != 0) {
DBName.erase(iter--);
}
}
std::transform(DBName.begin(), DBName.end(), DBName.begin(), ::tolower);//转小写
if (DBName == "mysql" || DBName == "sys" || DBName == "information_schema"
|| DBName == "performance_schema" || DBName == "serverobjects") {
std::cout << "该库不可删除!!";
}
mysql_close(&localMysql);
mysql_init(&localMysql);
std::string oper = "drop database " + DBName;
bool res = useQuery(&localMysql, oper);
return res;
}
//查看所有表
static bool checkAllTable(std::string DBName) {
bool res = useQuery(&localMysql, "show tables");
return res;
}
//创建表
static bool createTable(std::string tableName, std::string basicField, std::string fieldType, std::string key, std::string autoIncrement, std::string fieldComment, std::string tableComment = "") {
std::string oper = "create table if not exists `" + tableName + "` (`" + basicField + "` " + fieldType + " " + key
+ " " + autoIncrement + " comment '" + fieldComment + "')comment'" + tableComment + "'";
bool res = useQuery(&localMysql, oper.c_str());
return res;
}
//修改表名
static bool changeTableName(std::string tableName, std::string newTableName) {
std::string oper = "alter table `" + tableName + "` rename id `" + newTableName + "`";
bool res = useQuery(&localMysql, oper.c_str());
return res;
}
//删除表
static bool deleteTable(std::string tableName) {
MYSQL* mysql = &localMysql;
std::string oper = "drop table if exists`" + tableName + "`";
bool res = useQuery(mysql, oper.c_str());
return res;
}
//查看表结构:
static bool checkTableStructure(std::string tableName) {
MYSQL* mysql = &localMysql;
std::string oper = "desc `" + tableName + "`";
bool res = useQuery(mysql, oper.c_str());
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
int row = mysql_num_rows(result);
int column = mysql_num_fields(result);
MYSQL_ROW line = mysql_fetch_row(result);
std::string answer = "Field\tType\tNull\tKey\tDefault\tExtra\n";
while (line) {
for (int i = 0; i < column; i++) {
if (i) {
answer += "\t";
}
if (line[i]) {
answer += line[i];
}
else {
answer += "null";
}
}
answer += "\n";
line = mysql_fetch_row(result);
}
std::cout << answer << std::endl;
mysql_free_result(result);
}
return true;
}
//添加字段
static bool addField(std::string tableName, std::string fieldName, std::string fieldType, std::string key, std::string autoIncrement, std::string fieldComment) {
MYSQL* mysql = &localMysql;
std::string oper = "alter table `" + tableName + "` add `" + fieldName + "` " + fieldType + " " + key
+ " " + autoIncrement + " comment '" + fieldComment + "' ";
bool res = useQuery(mysql, oper.c_str());
return res;
}
//修改字段数据类型
static bool modifyFieldDataType(std::string tableName, std::string fieldName, std::string newDataType) {
MYSQL* mysql = &localMysql;
std::string oper = "alter table `" + tableName + "` modify `" + fieldName + "` " + newDataType;
bool res = useQuery(mysql, oper.c_str());
return res;
}
//修改字段名和类型
static bool changeFieldNameDataType(std::string tableName, std::string fieldName, std::string newFieldName, std::string newDataType) {
MYSQL* mysql = &localMysql;
std::string oper = "alter table `" + tableName + "`change `" + fieldName + "` `" + newFieldName + "` " + newDataType;
bool res = useQuery(mysql, oper.c_str());
return res;
}
//删除字段
static bool deleteField(std::string tableName, std::string fieldName) {
MYSQL* mysql = &localMysql;
std::string oper = "alter table `" + tableName + "` drop `" + fieldName + "`";
bool res = useQuery(mysql, oper.c_str());
return res;
}
//添加数据
static bool addData(std::string tableName, std::vector<std::string>fieldList, std::vector<std::vector<std::string>> dataList) {
std::string oper = "insert into `" + tableName + "`";
std::string FL, DL;
if (!fieldList.empty()) {//收集字段名
FL = " ( ";
for (int i = 0; i < fieldList.size(); i++) {
FL = FL + "`" + fieldList[i] + "`";
if (i < fieldList.size() - 1) {
FL += ", ";
}
}
FL += " ) ";
}
if (!dataList.empty()) {//收集要添加的数据
DL = " values ";
for (int i = 0; i < dataList.size(); i++) {
if (!dataList[i].empty()) {
DL += " ( ";
for (int j = 0; j < dataList[i].size(); j++) {
DL = DL + "'" + dataList[i][j] + "'";
if (j < dataList[i].size() - 1) {
DL += ", ";
}
}
DL += " ) ";
}
if (i < dataList.size() - 1) {
DL += ", ";
}
}
}
oper = oper + FL + DL;
bool res = useQuery(&localMysql, oper.c_str());
return res;
}
//修改数据
static bool modifyData(std::string tableName, std::vector<std::string>fieldList, std::vector<std::string>dataList, std::string condition) {
if (fieldList.size() != dataList.size()) {
std::cout << "字段个数数与相对应的值的个数不符! 字段有 " << fieldList.size() << " 个, 值有 " << dataList.size() << " 个。" << std::endl;
return false;
}
std::string oper = "update `" + tableName + "` set ";
for (int i = 0; i < fieldList.size(); i++) {
std::string tmp;
tmp = "`" + fieldList[i] + "` = " + dataList[i];
if (i < fieldList.size() - 1) {
tmp += ", ";
}
oper += tmp;
}
if (condition != "") {
oper = oper + " where " + condition;
}
bool res = useQuery(&localMysql, oper);
return res;
}
//删除数据
static bool deleteData(std::string tableName, std::string condition) {
std::string oper = "delete from `" + tableName + "` ";
if (condition != "") {
oper = oper + "where " + condition;
}
bool res = useQuery(&localMysql, oper);
return res;
}
//搜索函数及其重载
static bool selectTable(std::vector<std::string> fieldList, std::string tableName, std::string condition, std::vector<std::pair<std::string, std::string>> sortList) {
MYSQL* mysql = &localMysql;
std::string oper = "select ";
for (int i = 0; i < fieldList.size(); i++) {
oper = oper + "`" + fieldList[i] + "`";
if (i < fieldList.size() - 1) {
oper += ", ";
}
}
oper = oper + " from `" + tableName + "`";
if (!condition.empty()) {
oper += condition;
}
if (!sortList.empty()) {
oper += " order by ";
for (int i = 0; i < sortList.size(); i++) {
oper = oper + "`" + sortList[i].first + "` " + sortList[i].second;
if (i < sortList.size() - 1) {
oper += ", ";
}
}
}
bool res = useQuery(mysql, oper);
if (res) {
std::string ans;
for (int i = 0; i < fieldList.size(); i++) {
ans += fieldList[i];
if (i < fieldList.size() - 1) {
ans += "\t";
}
}
ans = ans + "\n" + basicSelect(mysql);
std::cout << ans << std::endl;
}
}
static bool selectTable(std::vector<std::string> fieldList, std::string tableName, std::string condition, std::string gropField, std::string gropCondition, std::vector<std::pair<std::string, std::string>> sortList, std::pair<std::string, std::string> paging) {
MYSQL* mysql = &localMysql;
std::string oper = "select ";
for (int i = 0; i < fieldList.size(); i++) {
oper = oper + "`" + fieldList[i] + "`";
if (i < fieldList.size() - 1) {
oper += ", ";
}
}
oper = oper + " from `" + tableName + "`";
if (!condition.empty()) {
oper += condition;
}
if (!gropField.empty()) {
oper = oper + " group by " + gropField;
if (!gropCondition.empty()) {
oper = oper + " having " + gropCondition;
}
}
if (!sortList.empty()) {
oper += " order by ";
for (int i = 0; i < sortList.size(); i++) {
oper = oper + "`" + sortList[i].first + "` " + sortList[i].second;
if (i < sortList.size() - 1) {
oper += ", ";
}
}
}
if (!(paging.first == "0" && paging.second == "0")) {
oper = oper + " limit " + paging.first + ", " + paging.second;
}
bool res = useQuery(mysql, oper);
if (res) {
std::string ans;
for (int i = 0; i < fieldList.size(); i++) {
ans += fieldList[i];
if (i < fieldList.size() - 1) {
ans += "\t";
}
}
ans = ans + "\n" + basicSelect(mysql);
std::cout << ans << std::endl;
}
}
//添加外键 功能不必要,暂时停止开发
/*static bool addForeignKey(std::string foreignTable, std::string foreighName, std::string foreighFieldName, std::string mainTable, std::string mainFieldName) {
MYSQL* mysql = &localMysql;
std::string oper = "alter table `" + foreignTable + "` add constraint `" + foreighName + "` foreign key " + ""
}*/
};
class Test {
public:
//设置考试
static void setTest() {
std::vector<std::string>dataList;
sendInf("请输入考试科目: ");
dataList.push_back(receiveInf());//string 50
sendInf("请输入考试分值: ");
dataList.push_back(receiveInf());//int 5
sendInf("请输入考试时间表,可换行。结束时另起一行输入 ~~~ 结束:\n");
dataList.push_back(receiveInf());//text 500
bool res = MysqlOperation::addData("subject", std::vector<std::string>{"subName", "fullScore", "time"}, std::vector<std::vector<std::string>>{dataList});
if (res) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (res) {
MysqlOperation::createTable(dataList[0], "id", "int", "", "", "", "");
MysqlOperation::addField(dataList[0], "studentName", "varchar(20)", "", "", "");
MysqlOperation::addField(dataList[0], "studentMajor", "varchar(20)", "", "", "");
MysqlOperation::addField(dataList[0], "studentGrade", "int", "", "", "");
MysqlOperation::addField(dataList[0], "studentClass", "int", "", "", "");
MysqlOperation::addField(dataList[0], "studentAccont", "int", "", "", "");
sendInf("设置成功!");
receiveInf();//保证程序正常运行
}
}
//创建试卷
static void createTest() {
MYSQL* mysql = &localMysql;
sendInf("请输入考试科目:");
std::string testName = receiveInf();//string 50
std::string oper = "select subName from `subject` where subName = '" + testName + "'";
bool res = MysqlOperation::useQuery(mysql, oper);
std::string test;
if (res) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (res) {
test = MysqlOperation::basicSelect(mysql);
bool ress = test.empty();
if (ress) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (ress) {
sendInf("未找到该科目的考试信息,是否先设置考试? 1:现在设置 2: 暂时不用\n请输入选择:");
std::string low = receiveInf();//num 1 de 2
if (low == "1") {
setTest();
}
else {
return;
}
}
else {
bool res1 = MysqlOperation::createTable(test + "test", "id", "int", "primary key", "auto_increment", "序号");
bool res2 = MysqlOperation::addField(test + "test", "type", "varchar(20)", "", "", "题目类型");
bool res3 = MysqlOperation::addField(test + "test", "topic", "varchar(1024)", "", "", "题目内容");
bool res4 = MysqlOperation::addField(test + "test", "score", "double", "", "", "分值");
bool res5 = MysqlOperation::addField(test + "test", "answer", "varchar(1024)", "", "", "答案");
addSubject(test + "test");
}
}
}
//添加试题
static void addSubject(std::string test) {
sendInf("请开始添加题目:\n");
receiveInf();//保证程序正常运行
std::vector< std::vector<std::string>> testList;
while (true) {
std::vector<std::string> testEdit;
sendInf("请选择题目类型,输入4退出添加题目: 1 选择题 2 填空题 3 大题: ");
std::string type = receiveInf();//num 1 de 0
if (type == "4") {
break;
}
if (type != "1" && type != "2" && type != "3") {
sendInf("暂不支持其他选项!\n");
receiveInf();//保证程序正常运行
continue;
}
testEdit.push_back(type);
std::string inf;
sendInf("请输入题目内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
testEdit.push_back(receiveInf());//text 1024 de 未输入
while (true) {
sendInf("请输入分值: ");
inf = receiveInf();//num 4 de -1
if (inf.c_str()[0] == '-' || inf == "0") {
sendInf("题目分值必须大于0,请重新设置!\n");
receiveInf();
continue;
}
break;
}
testEdit.push_back(inf);
if (type == "1") {
sendInf("请输入答案选项: ");
inf = receiveInf();//string 1 de 0
std::transform(inf.begin(), inf.end(), inf.begin(), ::toupper);
testEdit.push_back(inf);
}
else {
sendInf("请输入答案内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
testEdit.push_back(receiveInf());//text 1024 未输入
}
testList.push_back(testEdit);
sendInf("\n");
receiveInf();//保证程序正常运行
}
std::vector<std::string> fieldList = { "type", "topic", "score", "answer" };
MysqlOperation::addData(test, fieldList, testList);
}
//修改试题
static void modifySubject() {
MYSQL* mysql = &localMysql;
sendInf("请输入要修改删除试题的考试名称: ");
std::string subName = receiveInf();
MysqlOperation::useQuery(mysql, "show tables");
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row;
bool flags = false;
while (row = mysql_fetch_row(result)) {
if (row[0] == subName) {
flags = true;
break;
}
}
mysql_free_result(result);
if (!flags) {
sendInf("false");
}
else {
sendInf("true");
}
receiveInf();//保证程序正常运行
if (!flags) {
sendInf("没有该科目试卷");
receiveInf();//保证程序正常运行
}
else {
sendInf("当前试卷如下\n");
receiveInf();//保证程序正常运行
MysqlOperation::useQuery(mysql, "select * from `" + subName + "test`");
result = mysql_store_result(mysql);
int rnum = mysql_num_fields(result);
std::string ans;
while (row = mysql_fetch_row(result)) {
for (int i = 0; i < rnum; i++) {
if (i == 0) ans += "序号:";
if (i == 1) {
std::string ri = row[i];
if (ri == "1") {
ans += "类型:选择 代号:";
}
else if (ri == "2") {
ans += "类型:填空 代号:";
}
else if (ri == "3") {
ans += "类型:大题 代号:";
}
}
else if (i == 2) ans += "题目:\n";
else if (i == 3) ans += "分值:";
else if (i == 4) ans += "答案:";
ans += row[i];
ans += "\n";
}
ans += "\n";
}
sendInf(ans);//送出试卷
receiveInf();//保证程序正常运行
sendInf("请选择要修改的题目编号");
std::string number = receiveInf();//保证程序正常运行
sendInf("请重新输入题目:");
receiveInf();//保证程序正常运行
std::vector<std::string> testEdit;
while (true) {
sendInf("请选择题目类型: 1 选择题 2 填空题 3 大题: ");
std::string type = receiveInf();//num 1 de 0
if (type != "1" && type != "2" && type != "3") {
sendInf("暂不支持其他选项!\n");
receiveInf();//保证程序正常运行
continue;
}
testEdit.push_back(type);
std::string inf;
sendInf("请输入题目内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
testEdit.push_back(receiveInf());//text 1024 de 未输入
while (true) {
sendInf("请输入分值: ");
inf = receiveInf();//num 4 de -1
if (inf.c_str()[0] == '-' || inf == "0") {
sendInf("题目分值必须大于0,请重新设置!\n");
receiveInf();
continue;
}
break;
}
testEdit.push_back(inf);
if (type == "1") {
sendInf("请输入答案选项: ");
inf = receiveInf();//string 1 de 0
std::transform(inf.begin(), inf.end(), inf.begin(), ::toupper);
testEdit.push_back(inf);
}
else {
sendInf("请输入答案内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
testEdit.push_back(receiveInf());//text 1024 未输入
}
sendInf("\n");
receiveInf();//保证程序正常运行
break;
}
MysqlOperation::useQuery(mysql, "update `" + subName + "test` set type = '" + testEdit[0] + "', topic = '" + testEdit[1] + "', score = '" + testEdit[2] + "', answer = '" + testEdit[3] + "' where `id` = '" + number + "'");
sendInf("修改成功");
receiveInf();//保证程序正常运行
}
}
//删除题目
static void deleteSubject() {
MYSQL* mysql = &localMysql;
sendInf("请输入要修改删除试题的考试名称: ");
std::string subName = receiveInf();
MysqlOperation::useQuery(mysql, "show tables");
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row;
bool flags = false;
while (row = mysql_fetch_row(result)) {
if (row[0] == subName) {
flags = true;
break;
}
}
mysql_free_result(result);
if (!flags) {
sendInf("false");
}
else {
sendInf("true");
}
receiveInf();//保证程序正常运行
if (!flags) {
sendInf("没有该科目试卷");
receiveInf();//保证程序正常运行
}
else {
sendInf("当前试卷如下\n");
receiveInf();//保证程序正常运行
MysqlOperation::useQuery(mysql, "select * from `" + subName + "test`");
result = mysql_store_result(mysql);
int rnum = mysql_num_fields(result);
std::string ans;
while (row = mysql_fetch_row(result)) {
for (int i = 0; i < rnum; i++) {
if (i == 0) ans += "序号:";
if (i == 1) {
std::string ri = row[i];
if (ri == "1") {
ans += "类型:选择 代号:";
}
else if (ri == "2") {
ans += "类型:填空 代号:";
}
else if (ri == "3") {
ans += "类型:大题 代号:";
}
}
else if (i == 2) ans += "题目:\n";
else if (i == 3) ans += "分值:";
else if (i == 4) ans += "答案:";
ans += row[i];
ans += "\n";
}
ans += "\n";
}
sendInf(ans);//送出试卷
receiveInf();//保证程序正常运行
sendInf("请选择要删除的题目编号");
std::string number = receiveInf();//保证程序正常运行
MysqlOperation::useQuery(mysql, "delete from `" + subName + "test` where id = '" + number + "'");
}
}
//考试报名
static void signUp(std::vector<std::string> userInf) {
MYSQL* mysql = &localMysql;
std::string oper = "select `subName`, `time` from `subject` where `subName` is not null";
bool res = MysqlOperation::useQuery(mysql, oper);
if (res) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row;
std::vector<std::string> subjectList;
std::vector<std::string> timeList;
while (row = mysql_fetch_row(result)) {
subjectList.push_back(row[0]);
timeList.push_back(row[1]);
}
mysql_free_result(result);
sendInf("当前存在的考试科目及时间如下:\n");
receiveInf();//保证程序正常运行
int i = 0;
std::string low;
for (auto& j : subjectList) {
++i;
low = low + std::to_string(i) + ": " + j + "\n"
+ "时间:\n" + timeList[i - 1] + "\n\n";
}
sendInf(low);
receiveInf();//保证程序正常运行
sendInf("请输入要报名的序号: ");
std::string serial = receiveInf();//num 2 de -1
int se = (int)strToLf(serial);
bool lowss = se > subjectList.size() || se < 1;
if (lowss) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (lowss) {
sendInf("没有该考试信息!\n");
receiveInf();//保证程序正常运行
return;
}
else {
oper = "select `studentAccont` from `" + subjectList[se - 1] + "` where studentAccont = '" + userInf[1] + "'";
res = MysqlOperation::useQuery(mysql, oper);
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
if (row) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (row) {
sendInf("当前考试您已报名\n");
receiveInf();//保证程序正常运行
return;
}
mysql_free_result(result);
}
oper = "select `id`, `name`, `major`, `grade`, `class`, `accont` from student where accont = '" + userInf[1] + "'";
res = MysqlOperation::useQuery(mysql, oper);
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
int field = mysql_num_fields(result);
std::vector<std::string> oneStudent;
std::string id = row[0];
for (int i = 1; i < field; i++) {
oneStudent.push_back(row[i]);
}
mysql_free_result(result);
std::vector< std::vector<std::string>> studentList;
studentList.push_back(oneStudent);
std::vector<std::string> fieldList = { "studentName", "studentMajor","studentGrade","studentClass", "studentAccont" };
if (MysqlOperation::addData(subjectList[se - 1], fieldList, studentList)) {
std::vector<std::string> fieldList2 = { "id", "accont","subjectName" };
std::vector<std::string> data = { id,userInf[1],subjectList[se - 1] };
std::vector< std::vector<std::string>> dataIn = { data };
MysqlOperation::addData("entryForm", fieldList2, dataIn);
MysqlOperation::addField("student", subjectList[se - 1] + "Score", "double", "", "", "");
sendInf("报名成功\n");
receiveInf();//保证程序正常运行
}
else {
sendInf("报名失败\n");
receiveInf();//保证程序正常运行
}
}
}
}
}
//开始考试
static void beginTest(std::vector<std::string> userInf) {
MYSQL* mysql = &localMysql;
std::string oper = "select subjectName from `entryForm` where accont = '" + userInf[1] + "'";
bool res = MysqlOperation::useQuery(mysql, oper);
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
if (!row) sendInf("false");
else sendInf("true");
receiveInf();//保证程序正常运行
if (!row) {
sendInf("您当前未报名任何考试!\n");
receiveInf();//保证程序正常运行
}
else {
std::vector<std::string>nameList;
while (row) {
nameList.push_back(row[0]);
row = mysql_fetch_row(result);
}
mysql_free_result(result);
sendInf("以下当前报名的考试\n");
receiveInf();//保证程序正常运行
std::string sendss;
for (int i = 0; i < nameList.size(); i++) {
sendss = sendss + std::to_string(i + 1) + ":" + nameList[i] + "\n";
}
sendInf(sendss);//送出已报名的考试列表
receiveInf();//保证程序正常运行
sendInf("请输入要参加考试的序号:\n");
std::string se = receiveInf();//num 5 de -1
sendInf(std::to_string(nameList.size()));//送出考试数量
receiveInf();//保证程序正常运行
if (strToLf(se) < 1 || strToLf(se) > nameList.size()) {
sendInf("没有该选项\n");
receiveInf();//保证程序正常运行
}
else {
int sea = (int)strToLf(se);
std::string oper = "show tables";
res = MysqlOperation::useQuery(mysql, oper);
result = mysql_store_result(mysql);
bool have = false;
while (row = mysql_fetch_row(result)) {
if (row[0] == nameList[sea - 1] + "test") {
have = true;
break;
}
}
mysql_free_result(result);
if (!have) sendInf("false");
else sendInf("true");
receiveInf();//保证程序正常运行
if (!have) {
sendInf("当前考试老师还没有添加试卷\n");
receiveInf();//保证程序正常运行
}
else {
std::vector<double> scoreList(4);
std::string oper = "select `id`, `type`, `topic`, `score`, `answer` from `" + nameList[sea - 1] + "test`";
std::vector<std::vector<std::string>> testPaper;
MysqlOperation::useQuery(mysql, oper);
result = mysql_store_result(mysql);
row = mysql_fetch_row(result);
while (row) {
std::vector<std::string> subs;
for (int i = 0; i < 5; i++) {
subs.push_back(row[i]);
}
testPaper.push_back(subs);
row = mysql_fetch_row(result);
}
mysql_free_result(result);
std::vector<int> randomSubject = createRandList(1, testPaper.size());
sendInf(std::to_string(randomSubject.size()));//送出试题数量
receiveInf();//保证程序正常运行
for (int i = 0; i < randomSubject.size(); i++) {
std::string lows = "\n题目 " + std::to_string(i + 1) + ":\n" +
testPaper[randomSubject[i] - 1][2] + "\n" +
"该题分值: " + testPaper[randomSubject[i] - 1][3] + "\n";
sendInf(lows);
receiveInf();//保证程序正常运行
std::string answers;
sendInf(testPaper[randomSubject[i] - 1][1]);//送出试题类型
receiveInf();//保证程序正常运行
if (testPaper[randomSubject[i] - 1][1] == "1") {
sendInf("请输入选项: ");
answers = receiveInf();//string 15 de 未输入
std::transform(answers.begin(), answers.end(), answers.begin(), ::toupper);
if (testPaper[randomSubject[i] - 1][4] == answers) {
scoreList[0] += strToLf(testPaper[randomSubject[i] - 1][3]);
scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
}
}
else if (testPaper[randomSubject[i] - 1][1] == "2") {
sendInf("请输入答案: ");
answers = receiveInf();//string 500 ed 未输入
if (testPaper[randomSubject[i] - 1][4] == answers) {
scoreList[1] += strToLf(testPaper[randomSubject[i] - 1][3]);
scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
}
}
else {
sendInf("请输入答案:,输入完成后另起一行输入~~~上传答案 ");
answers = receiveInf();//text 1024 未输入
if (testPaper[randomSubject[i] - 1][4] == answers) {
scoreList[2] += strToLf(testPaper[randomSubject[i] - 1][3]);
scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
}
}
}
sendInf("正在记录成绩...\n");
receiveInf();//保证程序正常运行
std::vector<std::string> fieldList = { nameList[sea - 1] + "Score" };
std::vector<std::string> sc = { lfToStr(scoreList[3]) };
MysqlOperation::modifyData("student", fieldList, sc, " accont = '" + userInf[1] + "'");
MysqlOperation::addData(nameList[sea - 1], std::vector<std::string>{"studentName", "studentMajor", "studentGrade", "studentClass", "studentAccont"}, std::vector<std::vector<std::string>>{std::vector<std::string>{userInf[2], userInf[3], userInf[4], userInf[5], userInf[1]}});
sendInf("记录完成!\n\n");
receiveInf();//保证程序正常运行
std::string lowss = "\n考试已完成, 题目已由系统批改,其中:\n选择题得分: "
+ std::to_string(scoreList[0]) + "\n"
+ "填空题得分: " + std::to_string(scoreList[1]) + "\n"
+ "大题得分: " + std::to_string(scoreList[2]) + "\n\n"
+ "填空题,大题部分由于本系统的无能或许会出现误判,请等待老师手动重批,以上成绩仅供参考\n";
sendInf(lowss);
receiveInf();//保证程序正常运行
}
}
}
}
}
//查看成绩
static void checkResult(std::vector<std::string> userInf) {
MYSQL* mysql = &localMysql;
MYSQL_RES* result;
MYSQL_ROW row;
std::string oper;
std::vector<std::string> subjectName;
oper = "select subjectName from `entryForm` where accont = '" + userInf[1] + "'";
bool res = MysqlOperation::useQuery(mysql, oper);
if (res) {
result = mysql_store_result(mysql);
while (row = mysql_fetch_row(result)) {
subjectName.push_back(row[0]);
}
mysql_free_result(result);
}
oper = "select ";
for (int i = 0; i < subjectName.size(); i++) {
oper = oper + "`" + subjectName[i] + "Score`";
if (i < subjectName.size() - 1) {
oper += ",";
}
}
oper = oper + " from student where accont = '" + userInf[1] + "'";
res = MysqlOperation::useQuery(mysql, oper);
if (res) {
result = mysql_store_result(mysql);
MYSQL_FIELD* field;
std::string low;
while (field = mysql_fetch_field(result)) {
low += field->name;
low += "\t";
}
sendInf(low);
receiveInf();//保证程序正常运行
sendInf("\n");
receiveInf();//保证程序正常运行
int column = mysql_num_fields(result);
std::string ans;
MYSQL_ROW row = mysql_fetch_row(result);
while (row) {
for (int i = 0; i < column; i++) {
if (row[i]) {
ans += row[i];
}
else {
ans += "null";
}
if (i < column - 1) {
ans += "\t";
if (i >= 7) {
ans += "\t";
}
}
}
ans += "\n";
row = mysql_fetch_row(result);
}
sendInf(ans);
receiveInf();//保证程序正常运行
mysql_free_result(result);
}
}
};
class User {
public:
//登录
static std::vector<std::string> signIn() {
MYSQL* mysql;
MYSQL_RES* result;
MYSQL_ROW password;
std::vector<std::string> re;
while (true) {
std::string sendOut = R"(
登录:
请选择身份:
1 教师
2 学生
请输入序号:)";
sendInf(sendOut);//送出身份选择
std::string order = receiveInf();//获得身份
re.push_back(order);//储存身份
std::vector<std::string> inf;
sendInf("server: 请输入账号:");
inf.push_back(receiveInf());//获得账号 string 20
sendInf("server: 请输入密码:");
inf.push_back(receiveInf());//获得密码 string 15
mysql = &localMysql;
std::string tors = "student";
if (order == "1") tors = "teacher";
std::string oper = "select `password` from `" + tors + "` where accont = '" + inf[0] + "'";
bool res = MysqlOperation::useQuery(mysql, oper);
result = mysql_store_result(mysql);
password = mysql_fetch_row(result);
std::string iferror = "false";
if (!password) {
iferror = "true";
}
sendInf(iferror);//发送错误情况
receiveInf();//保证正常运行
if (!password) {
mysql_free_result(result);
sendInf("server: 用户不存在,是否要创建账户? 1:创建 2:取消 请输入序号:");
std::string ins = receiveInf();//获得选择
if (ins == "1") {
userCreate();
}
continue;
}
else {
bool ifR = password[0] == inf[1];
if (ifR) sendInf("true");
else sendInf("false");
receiveInf();//保证正常运行
if (ifR) {
mysql_free_result(result);
bool low = MysqlOperation::useQuery(mysql, "select `accont`, `name`, `major`, `grade`, `class` from `student` where accont = '" + inf[0] + "'");
if (low) sendInf("true");//送出查询情况
else sendInf("false");//送出查询情况
receiveInf();//保证正常运行
if (low) {
result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
if (row) {
for (int i = 0; i < 5; i++) {
re.push_back(row[i]);
}
}
mysql_free_result(result);
sendInf("server: 登陆成功!");//送出选择
receiveInf();//保证正常运行
return re;
}
else {
sendInf("server: 登陆失败!");//送出选择
receiveInf();//保证正常运行
continue;
}
}
else {
sendInf("server: 账号或密码错误");
receiveInf();//保证正常运行
continue;
}
}
}
}
//创建用户
static void userCreate() {
sendInf(R"(
请选择您的身份:
1 教师
2 学生
请输入序号:)");
std::string order = receiveInf();//获得身份
std::vector<std::string> inf;
sendInf("server: 请输入姓名:");
inf.push_back(receiveInf());//获得姓名,string 20
sendInf("server: 请输入专业:");
inf.push_back(receiveInf());//获得专业,string 20
if (order == "2") {
sendInf("server: 请输入年级:");
inf.push_back(receiveInf());//获得年级,int 2
sendInf("server: 请输入班级:");
inf.push_back(receiveInf());//获得班级 int 2
}
sendInf("server: 请输入电话:");
inf.push_back(receiveInf());//string 11
sendInf("server: 请输入账号:");
inf.push_back(receiveInf());//string 20
sendInf("server: 请输入密码:");
inf.push_back(receiveInf());//string 15
std::string tors = "student";
if (order == "1") tors = "teacher";
MYSQL* mysql = &localMysql;
std::string oper = "select * from `" + tors + "` where accont = " + inf[3];
bool res = MysqlOperation::useQuery(mysql, oper);
if (res) sendInf("true");//送出查询情况
else sendInf("false");//送出查询情况
receiveInf();//保证正常运行
if (res) {
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW accont = mysql_fetch_row(result);
std::string ifExit = "false";
if (accont) {
ifExit = "true";
}
sendInf(ifExit);//送出账号是否存在的状态
receiveInf();//保证正常运行
if (accont) {
sendInf("server: 用户已存在!");
receiveInf();//保证正常运行
}
else {
std::vector<std::string> field;
field.push_back("name");
field.push_back("major");
if (order == "2") {
field.push_back("grade");
field.push_back("class");
}
field.push_back("phone");
field.push_back("accont");
field.push_back("password");
std::vector<std::vector<std::string>> infIn;
infIn.push_back(inf);
bool res = MysqlOperation::addData(tors, field, infIn);
if (res) {
sendInf("server: 创建成功!");
receiveInf();//保证正常运行
}
else {
sendInf("server: 创建失败!");
receiveInf();//保证正常运行
}
}
mysql_free_result(result);
}
else {
std::cout << mysql_error(mysql) << std::endl;
}
}
static void modifyUser() {
MYSQL* mysql = &localMysql;
sendInf("请输入要修改的用户的身份:\n1:教师\n2:学生\n请输入:");
std::string orders = receiveInf();
if (orders == "1") {
orders = "teacher";
}
else {
orders = "student";
}
sendInf("请输入要修改的用户账号:\n");
std::string accont = receiveInf();
MysqlOperation::useQuery(mysql, "select * from `" + orders + "` where accont = '" + accont + "'");
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
if (row) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (!row) {
sendInf("未找到该用户...\n");
receiveInf();//保证程序正常运行
}
else {
sendInf("已找到该用户:\n");
receiveInf();//保证程序正常运行
std::string fieldList;
std::string datas;
std::vector<std::string> infList;
MYSQL_FIELD* field;
while (field = mysql_fetch_field(result)) {
fieldList += field->name;
fieldList += "\t";
}
fieldList += "\n";
int fnum = mysql_num_fields(result);
while (row) {
for (int i = 0; i < fnum; i++) {
infList.push_back(row[i]);
datas = datas + row[i] + "\t";
}
row = mysql_fetch_row(result);
}
mysql_free_result(result);
datas += "\n";
sendInf(fieldList + datas);//送出当前用户信息
receiveInf();//保证程序正常运行
sendInf("请开始修改以下信息,不修改的按回车跳过: \n");
receiveInf();//保证程序正常运行
std::vector<std::string> dataList;
sendInf(infList[1]);//送出老姓名
receiveInf();//保证程序正常运行
sendInf("姓名:");
dataList.push_back(receiveInf());//获得新姓名
sendInf(infList[2]);//送出老专业
receiveInf();//保证程序正常运行
sendInf("专业:");
dataList.push_back(receiveInf());//获得新专业
if (orders == "student") {
sendInf(infList[3]);//送出老年级
receiveInf();//保证程序正常运行
sendInf("年级:");
dataList.push_back(receiveInf());//获得新年级
sendInf(infList[4]);//送出老班级
receiveInf();//保证程序正常运行
sendInf("班级:");
dataList.push_back(receiveInf());//获得新班级
sendInf(infList[5]);//送出老电话
receiveInf();//保证程序正常运行
sendInf("电话:");
dataList.push_back(receiveInf());//获得新电话
sendInf(infList[6]);//送出老账号
receiveInf();//保证程序正常运行
sendInf("账号:");
dataList.push_back(receiveInf());//获得新账号
sendInf(infList[7]);//送出老密码
receiveInf();//保证程序正常运行
sendInf("密码:");
dataList.push_back(receiveInf());//获得新密码
MysqlOperation::useQuery(mysql, "update `" + orders + "` set `name` = '" + dataList[0] + "', `major` = '" + dataList[1] + "', `grade` = '" + dataList[2] + "', `class` = '" + dataList[3] + "', `phone` = '" + dataList[4] + "', `accont` = '" + dataList[5] + "', `password` = '" + dataList[6] + "'");
}
else {
sendInf(infList[3]);//送出老电话
receiveInf();//保证程序正常运行
sendInf("电话:");
dataList.push_back(receiveInf());//获得新电话
sendInf(infList[4]);//送出老账号
receiveInf();//保证程序正常运行
sendInf("账号:");
dataList.push_back(receiveInf());//获得新账号
sendInf(infList[5]);//送出老密码
receiveInf();//保证程序正常运行
sendInf("密码:");
dataList.push_back(receiveInf());//获得新密码
MysqlOperation::useQuery(mysql, "update `" + orders + "` set `name` = '" + dataList[0] + "', `major` = '" + dataList[1] + "', `phone` = '" + dataList[2] + "', `accont` = '" + dataList[3] + "', `password` = '" + dataList[4] + "'");
}
sendInf("修改完成");//送出信息
receiveInf();//保证程序正常运行
}
}
static void deleteUser() {
MYSQL* mysql = &localMysql;
sendInf("请输入要删除的用户的身份:\n1:教师\n2:学生\n请输入:");
std::string orders = receiveInf();
if (orders == "1") {
orders = "teacher";
}
else {
orders = "student";
}
sendInf("请输入要删除的用户账号:\n");
std::string accont = receiveInf();
MysqlOperation::useQuery(mysql, "select * from `" + orders + "` where accont = '" + accont + "'");
MYSQL_RES* result = mysql_store_result(mysql);
MYSQL_ROW row = mysql_fetch_row(result);
if (row) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (!row) {
sendInf("未找到该用户...\n");
receiveInf();//保证程序正常运行
}
else {
sendInf("已找到该用户:\n");
receiveInf();//保证程序正常运行
std::string fieldList;
std::string datas;
std::vector<std::string> infList;
MYSQL_FIELD* field;
while (field = mysql_fetch_field(result)) {
fieldList += field->name;
fieldList += "\t";
}
fieldList += "\n";
int fnum = mysql_num_fields(result);
while (row) {
for (int i = 0; i < fnum; i++) {
infList.push_back(row[i]);
datas = datas + row[i] + "\t";
}
row = mysql_fetch_row(result);
}
mysql_free_result(result);
datas += "\n";
sendInf(fieldList + datas);//送出当前用户信息
receiveInf();//保证程序正常运行
sendInf("是否删除? 1:是 2:否 请输入选择:");//送出当前用户信息
std::string ifd = receiveInf();
if (ifd == "1") {
MysqlOperation::useQuery(mysql, "delete from `" + orders + "` where accont = '" + accont + "'");
sendInf("删除完成\n");
receiveInf();//保证程序正常运行
}
else {
sendInf("取消删除\n");
receiveInf();//保证程序正常运行
}
}
}
};
bool flagss = true;
//界面与登录
class Visualization {
public:
//初始化
static void initialization() {
system("color E1");
std::cout << "正在初始化系统..." << std::endl;
std::string DBname = "ExaminationSystem";
MysqlOperation useSql;
useSql.ConnectDB("localhost", "root", "@Shang123", "mysql", 3306);
useSql.checkIfConnectDB();
std::cout << "正在创建基础表结构..." << std::endl;
useSql.createTable("teacher", "id", "int", "primary key", "auto_increment", "序号", "教师信息");
useSql.createTable("student", "id", "int", "primary key", "auto_increment", "序号", "学生信息");
useSql.createTable("subject", "id", "int", "primary key", "auto_increment", "序号", "考试科目");
useSql.createTable("entryForm", "id", "int", "", "", "学生序号", "考试科目");
useSql.addField("teacher", "name", "varchar(20)", "", "", "姓名");
useSql.addField("teacher", "major", "varchar(20)", "", "", "专业");
useSql.addField("teacher", "phone", "char(11)", "", "", "电话");
useSql.addField("teacher", "accont", "varchar(20)", "", "", "账号");
useSql.addField("teacher", "password", "varchar(15)", "", "", "密码");
useSql.addField("student", "name", "varchar(20)", "", "", "姓名");
useSql.addField("student", "major", "varchar(20)", "", "", "专业");
useSql.addField("student", "grade", "int", "", "", "年级");
useSql.addField("student", "class", "int", "", "", "班级");
useSql.addField("student", "phone", "char(11)", "", "", "电话");
useSql.addField("student", "accont", "varchar(20)", "", "", "账号");
useSql.addField("student", "password", "varchar(15)", "", "", "密码");
useSql.addField("subject", "subName", "varchar(50)", "", "", "科目名");
useSql.addField("subject", "fullScore", "int", "", "", "分值");
useSql.addField("subject", "time", "varchar(500)", "", "", "考试时间表");
useSql.addField("entryForm", "accont", "varchar(20)", "", "", "学生账号");
useSql.addField("entryForm", "subjectName", "varchar(50)", "", "", "报名科目");
std::cout << "创建成功..." << std::endl;
std::cout << "初始化完成!" << std::endl;
system("pause");
}
//学生开始界面
static void begin(std::string identity) {
if (identity == "2") {
sendInf(R"(
?---------------0-0-0---------------?
| |
| 欢迎使用 好果zhi考试系统 |
| 本系统暂时没什么要给你说的... |
| 功能指令如下: |
| 1 登录 |
| 2 创建用户 |
| 3 考试报名 |
| 4 进行考试 |
| 5 查看成绩 |
| 6 离开系统 |
| author:阿白 |
| 2022/10/26 |
|___________________________________|
)");
receiveInf();//保证正常运行
}
else {
sendInf(R"(
?---------------(>v<)---------------?
| |
| 欢迎使用 好果zhi考试系统 |
| 本系统暂时没什么要给你说的... |
| 功能指令如下: |
| 1 登录 |
| 2 创建用户 |
| 3 修改用户 |
| 4 删除用户 |
| 5 设置考试 |
| 6 创建试卷 |
| 7 添加试题 |
| 8 修改试题 |
| 9 删除试题 |
| 0 离开系统 |
| author:阿白 |
| 2022/10/26 |
|___________________________________|
)");
receiveInf();//保证正常运行
}
}
static std::string end() {//告别界面
sendInf(R"(
!---------------(=_=)---------------!
| |
| 就要告别了呢... |
| ... |
| 考试不快乐吗 |
| 还是本系统不好用呢 |
| |
| ########################### |
| ########################### |
| ...好吧 |
| 期待下次相见 |
| >_< |
|___________________________________|
)");
return receiveInf();//服务端是否要求主机关机
}
//登录界面
static std::vector<std::string> signInVisual() {
std::vector<std::string> userInf;
while (flagss) {
std::string face = R"(
←---------------------- UnU ----------------------→
` 注意: `
` `
` 在使用这个考试系统前,本系统要验证一下你的身份!`
` 所以: `
` `
` 请先:1 登录 2 注册 `
请输入序号:)";
sendInf(face);
std::string useMySystem = receiveInf();//获得选择
if (useMySystem == "1") {
userInf = User::signIn();
flagss = false;
}
else {
User::userCreate();
continue;
}
if (userInf.empty()) sendInf("true");
else sendInf("false");
receiveInf();//保证程序正常运行
if (userInf.empty()) {
continue;
}
break;
}
return userInf;
}
};
//子线程
DWORD WINAPI realize(LPVOID);
bool ts = false;
//socket初始化
bool socInitlz() {
WSADATA* wsaData = &localWsaData;
int res;
if (!WSAStartup(MAKEWORD(2, 2), wsaData)) {
std::cout << "绑定socket库成功" << std::endl;
}
else {
std::cout << "绑定socket库失败" << std::endl;
return false;
}
if (2 != LOBYTE(localWsaData.wVersion) || 2 != HIBYTE(localWsaData.wVersion)) {
WSACleanup();
std::cout << "WSADATA的版本不正确" << std::endl;
return false;
}
//创建套接字
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
//绑定套接字,配置监听地址和端口
SOCKADDR_IN svrAddr;
ZeroMemory((char*)&svrAddr, sizeof(svrAddr));
svrAddr.sin_family = AF_INET; //国际网区域
svrAddr.sin_port = htons(6000); //监听端口
svrAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //有IP
if (::bind(serverSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
std::cout << "配置监听失败: " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return false;
}
//监听
if (::listen(serverSocket, 10) == SOCKET_ERROR) {//最大连接数10个
std::cout << "system: 开启监听失败 " << WSAGetLastError() << std::endl;
closesocket(serverSocket);
WSACleanup();
return false;
}
std::cout << "system: 开启监听成功\n";
//接收套接字
SOCKADDR_IN clientAddr;
int length = sizeof(SOCKADDR);
//接收连接
if ((connectSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &length)) == INVALID_SOCKET) {
std::cout << "system: 接收消息失败" << WSAGetLastError() << std::endl;
closesocket(connectSocket);
WSACleanup();
return false;
}
HANDLE sendThread = CreateThread(nullptr, 0, realize, 0, 0, nullptr);
if (sendThread) {
CloseHandle(sendThread);
}
hMUTEX = CreateMutex(NULL, FALSE, L"mutex");
while (true) {
if (ts) {
std::cout << "客户端请求终止服务...";
break;
}
Sleep(100);
}
closesocket(serverSocket);
closesocket(connectSocket);
WSACleanup();
return true;
}
int main()
{
Visualization::initialization();
MYSQL* mysql = &localMysql;
system("cls");
socInitlz();//初始化服务端并使用线程
return 0;
}
DWORD WINAPI realize(LPVOID) {
std::vector<std::string> userInf;
userInf = Visualization::signInVisual();
sendInf(userInf[0]);//传递身份
receiveInf();//保证程序正常运行
while (true) {
Visualization::begin(userInf[0]);
sendInf("请输入您的指令: ");
std::string ins = receiveInf();//获得指令
if (ins == "1") {//登录
userInf = User::signIn();
}
else if(ins == "2") {//注册
User::userCreate();
userInf = User::signIn();
}
else if (ins == "3") {
if (userInf[0] == "1") {
User::modifyUser();//修改用户
}
else {
Test::signUp(userInf);//考试报名
}
}
else if (ins == "4") {
if (userInf[0] == "1") {
User::deleteUser();//删除用户
}
else {
Test::beginTest(userInf);//开始考试
}
}
else if(ins == "5") {
if (userInf[0] == "1") {
//创建考试
Test::setTest();
}
else {
Test::checkResult(userInf);//查看成绩
}
}
else if (ins == "6") {
if (userInf[0] == "1") {
Test::createTest();
}
else {
Visualization::end();
ts = true;
return 0;
}
}
else if (ins == "7") {
//添加试题
sendInf("请输入要添加题目的试卷名称:");
std::string subname = receiveInf();//string 50 未输入
Test::addSubject(subname + "test");
}
else if (ins == "8") {
Test::modifySubject();//修改试题
}
else if (ins == "9") {
Test::deleteSubject();//删除试题
}
else {
Visualization::end();
ts = true;
return 0;
}
}
}
2.客户端的创建?
头文件的添加同服务端
代码:
#include "stdafx.h"
//便捷读取
class SafeRead
{
public:
//录入数字
static std::string readNum(int length, const std::string& oldNum) {
std::string inf;
//label位置
label:while (true) {
std::cout << " 请输入数字:";
getline(std::cin, inf);
if (inf == "\n" || inf.empty()) {
return oldNum;
}
else if ((int)inf.length() > length) {
std::cout << "\n\t长度超过" << length << "位(计算需要包含小数点),请重新输入。\n";
continue;
}
std::stringstream sin(inf);
double d;
char c;
bool flag = true;
if (!(sin >> d))
flag = false;
if (sin >> c)
flag = false;
if (!flag) {
std::cout << "输入的不是一个数字,请重新输入" << std::endl;
continue;
}
break;
}
//删除前导零
std::string::iterator it = inf.begin();
for (unsigned int i = 0; i < inf.length() - 1; i++) {//单0不删,一串0只留一个
if (inf[i] == '-') continue;
if (inf[i] != '0') break;
if (inf[i] == '0' && inf[i + 1] == '.') break;
inf.erase(it);
it++;
}
return inf;
}
//录入有限制的字符串,用于读取基本信息
static std::string readString(int length, std::string old) {
std::string inf;
while (true) {
getline(std::cin, inf);
if (inf == "\n" || inf.empty()) {
return old;
}
else if ((int)inf.length() > length) {
std::cout << "\n\t信息长度超过" << length << ",请重新输入。\n";
continue;
}
return inf;
}
}
//读取文本块,以~~~结束
static std::string readText(int length, std::string old) {
while (true) {
std::string ans;
while (true) {
std::string inf;
getline(std::cin, inf);
if (inf == "~~~") {
break;
}
else {
ans = ans + inf + "\n";
}
}
if (ans.size() > length) {
std::cout << "当前文本长度(包括空格)为 " << ans.size() << ",已超过限定长度 " << length << ",请重新输入..." << std::endl;
continue;
}
return ans;
}
}
};
double strToLf(const std::string& number) {
double lf = 0, lfi = 0, x = 10;
int i = 0, f = 1, times = 1, length = (int)number.length();
while (number[i] < '0' || number[i] > '9') {//跳过可能存在的¥,$ 或 -
i++;
if (number[i] == '-')
f *= -1;
}
//整数位
while (i < length) {
if (number[i] == '.') {
break;
}
lf = lf * 10 + number[i] - '0';
i++;
}
//小数位,++i跳过‘ . ’
while (++i < length) {
lfi += (number[i] - '0') / x;
x *= 10;
}
return times * f * (lf + lfi);
}
WSADATA localWsaData;
SOCKET clientSocket;
HANDLE hMUTEX;
DWORD WINAPI realize(LPVOID);
DWORD WINAPI receiver(LPVOID);
using std::cout;
using std::endl;
int sendInf(std::string sendBuff);
std::string receiveInf();
void rev();
void createUser();
std::string signIn();
void setTest();
void createTest();
void addSubject();
void signUp();
void beginTest();
void checkResult();
void modifySubject();
void deleteSubject();
void modifyUser();
void deleteUser();
//客户端线程
DWORD WINAPI realize(LPVOID);
bool ts = false;
int main() {
WSADATA* wsaData = &localWsaData;
if (WSAStartup(MAKEWORD(1, 1), wsaData)) {
std::cout << "加载WinSock错误" << std::endl;
return false;
}
else {
std::cout << "加载WinSock成功" << std::endl;
}
if (LOBYTE(localWsaData.wVersion) != 1 || HIBYTE(localWsaData.wVersion) != 1) {
WSACleanup();
return false;
}
//创建套接字
clientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (clientSocket == INVALID_SOCKET) {
std::cout << "套接字库创建失败" << std::endl;
}
else {
std::cout << "套接字库创建成功" << std::endl;
}
//与服务端连接
SOCKADDR_IN svrAddr;
svrAddr.sin_family = AF_INET; //国际网区域
svrAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//服务端IP
svrAddr.sin_port = htons(6000); //监听端口
if (connect(clientSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
std::cout << "连接错误: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return false;
}
std::cout << "连接服务端成功" << std::endl;
//创建子线程
HANDLE sendThread = CreateThread(nullptr, 0, realize, 0, 0, nullptr);
if (sendThread) {
CloseHandle(sendThread);
}
hMUTEX = CreateMutex(NULL, FALSE, L"mutex");
//给予线程使用
while (1) {
if (ts) {
return 0;
}
Sleep(100);
}
closesocket(clientSocket);
WSACleanup();
return 0;
}
bool flag = false;
DWORD WINAPI realize(LPVOID) {
while (!flag) {
system("color E1");
system("cls");
std::string order;
rev();//获取开始登录界面
std::string ins = SafeRead::readNum(1, "1");
sendInf(ins);//送出选择
if (ins == "1") {
signIn();
flag = true;
}
else {
createUser();
continue;
}
std::string ifempty = receiveInf();
sendInf("");//保证程序正常运行
if (ifempty == "true") {
continue;
}
break;
}
std::string userInf = receiveInf();//获得身份
sendInf("");//保证程序正常运行
while (true) {
system("cls");
rev();//获得开始界面
sendInf("");//保证程序正常运行
rev();//请输入您的指令提醒
std::string inf = SafeRead::readNum(1, "1");
sendInf(inf);//送出指令
if (inf == "1") {//登录
userInf = signIn();
}
else if (inf == "2") {
createUser();
userInf = signIn();
}
else if (inf == "3") {
if (userInf == "1") {
modifyUser();
}
else {
signUp();//考试报名
}
}
else if (inf == "4") {
if (userInf == "1") {
deleteUser();
}
else {
beginTest();//开始考试
}
}
else if (inf == "5") {
if (userInf == "1") {
setTest();//设置考试
}
else {
checkResult();//查看成绩
}
}
else if (inf == "6") {
if (userInf == "1") {
createTest();//创建试卷
}
else {
rev();//获得告别界面
sendInf("1");//由于现在只连一个客户端,直接让服务端也关闭算了
ts = true;
system("pause");
return 0;
}
}
else if (inf == "7") {
rev();//
sendInf(SafeRead::readString(50, "未输入"));//输入试卷名
addSubject();//添加试题
}
else if (inf == "8") {
modifySubject();//修改试题
}
else if(inf == "9") {
deleteSubject();//删除试题
}
else {
rev();//获得告别界面
sendInf("1");//由于现在只连一个客户端,直接让服务端也关闭算了
ts = true;
system("pause");
return 0;
}
system("pause");
}
}
int sendInf(std::string sendBuff) {
sendBuff += '\0';
if (sendBuff == "#") {
sendBuff = "system: 用户端请求终止对话...\n";
}
int ret = send(clientSocket, sendBuff.c_str(), sizeof(char) * sendBuff.size(), 0);
if (ret == SOCKET_ERROR) {
std::cout << "system: 发送失败: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return -1;
}
else if (ret == 0) {
std::cout << "system: 服务端断开连接: " << std::endl;
closesocket(clientSocket);
WSACleanup();
return 0;
}
else {
return 1;
}
}
std::string receiveInf() {
char recvBuff[3000]{};
int flag = recv(clientSocket, recvBuff, 3000, 0);
if (flag == SOCKET_ERROR) {
std::cout << "system: 接收消息失败: " << WSAGetLastError();
closesocket(clientSocket);
WSACleanup();
return "";
}
else if (!flag) {
std::cout << "system: 服务端断开连接: " << WSAGetLastError();
closesocket(clientSocket);
WSACleanup();
return "";
}
return recvBuff;
}
void rev() {//简化需要直接输出的接收数据
cout << receiveInf() << endl;
}
//登录
std::string signIn() {
while (true) {
std::string order;
rev();//获取身份选择界面
order = SafeRead::readNum(1, "1");//选择身份 1 教师 2 学生
sendInf(order);
rev();//接收身份报错
sendInf(SafeRead::readString(20, "未输入"));//送出账号 最长20
rev();//保证正常运行
sendInf(SafeRead::readString(15, "未输入"));//送出密码 最长15
std::string iferror = receiveInf();//接收错误情况
sendInf("");//保证正常运行
if (iferror == "true") {
rev();//接收是否需要现在创建用户的选择 1 创建 2 不创建
std::string ifc = SafeRead::readNum(1, "2");
sendInf(ifc);//送出选择
if (ifc == "1") {
createUser();
}
continue;
}
else {
std::string ifR = receiveInf();//接收密码是否正确的情况
sendInf("");//保证正常运行
if (ifR == "true") {
std::string low = receiveInf();//接收查询情况
sendInf("");//保证正常运行
if (low == "true") {
rev();//接收登陆成功提醒
sendInf("");//保证正常运行
return order;
}
else {
rev();//接收登录失败提醒
sendInf("");//保证正常运行
continue;
}
}
else {
rev();//接收密码错误的提示
sendInf("");//保证正常运行
continue;
}
}
}
}
void createUser() {
rev();//获得身份选择界面
std::string order = SafeRead::readNum(1, "1");//做出身份选择
sendInf(order);
rev();//提示输入姓名
sendInf(SafeRead::readString(20, "未输入"));//送出姓名
rev();
sendInf(SafeRead::readString(20, "未输入"));//送出专业
if (order == "2") {
rev();
sendInf(SafeRead::readNum(2, "-1"));//送出年级
rev();
sendInf(SafeRead::readNum(2, "-1"));//送出班级
}
rev();
sendInf(SafeRead::readString(11, "未输入"));//送出电话
rev();
sendInf(SafeRead::readString(20, "未输入"));//送出账号
rev();
sendInf(SafeRead::readString(15, "未输入"));//送出密码
std::string ins = receiveInf();//接收搜索状态
sendInf("");//保证正常运行
if (ins == "true") {
std::string low = receiveInf();
sendInf("");//保证正常运行
if (low == "true") {//判断账号是否存在的搜索//保证正常运行
rev();//接收账号已存在的反馈
sendInf("");//保证正常运行
}
else {
rev();//打印创建反馈
sendInf("");//保证正常运行
}
}
else {
cout << "\n创建出现错误" << endl;
}
}
void setTest() {
rev();
sendInf(SafeRead::readString(50, "未输入"));//传递考试科目
rev();
sendInf(SafeRead::readNum(5, "-1"));//传递考试分值
rev();
sendInf(SafeRead::readText(500, "未输入"));//传递考试时间表
std::string low = receiveInf();//接收res
sendInf("");//保证程序正常运行
if (low == "true") {
rev();//接收设置成功的消息
sendInf("");//保证程序正常运行
}
}
void createTest() {
rev();
sendInf(SafeRead::readString(50, "未输入"));//传递考试科目
std::string low = receiveInf();//接收res
sendInf("");//保证程序正常运行
if (low == "true") {
std::string res = receiveInf();//接收该科目考试是否为空的消息
sendInf("");//保证程序正常运行
if (res == "true") {
rev();//接收现在是否设置考试的消息 1 设置 2 不设置
std::string lows = SafeRead::readNum(1, "2");
sendInf(lows);//传递选择
if (lows == "1") {
setTest();
}
else {
return;
}
}
else {
addSubject();
}
}
}
void addSubject() {
rev();//接收请开始添加试题的提示
sendInf("");//保证程序正常运行
while (true) {
std::string type;
rev();//选择题目类型
type = SafeRead::readNum(1, "1");
sendInf(type);//传入题目类型
if (type == "4") {
break;
}
if (type != "1" && type != "2" && type != "3") {
rev();//无该类型的提醒
sendInf("");//保证程序正常运行
}
rev();
sendInf(SafeRead::readText(1024, "未输入"));//传入题目类型
while (true) {
rev();//请输入分值的提醒
std::string inf = SafeRead::readNum(4, "-1");
sendInf(inf);//传递分值
if (inf.c_str()[0] == '-' || inf == "0") {
rev();//分值大于0提醒
sendInf("");
continue;
}
break;
}
if (type == "1") {
rev();//请输入答案选项提醒
sendInf(SafeRead::readString(1, "0"));//获得答案
}
else {
rev();
sendInf(SafeRead::readText(1024, "未输入"));//获得答案
}
rev();//接收回车
sendInf("");//保证程序正常运行
}
}
void signUp() {
std::string res = receiveInf();//读取res
sendInf("");//保证程序正常运行
if (res == "true") {
rev();//接收考试科目提示
sendInf("");//保证程序正常运行
rev();//接收考试科目及时间
sendInf("");//保证程序正常运行
rev();//报名序号提醒
sendInf(SafeRead::readNum(2, "-1"));
std::string low = receiveInf();//接收序号是否正确信息
sendInf("");//保证程序正常运行
if (low == "true") {
rev();//没有考试提醒
sendInf("");//保证程序正常运行
}
else {
low = receiveInf();//接收row
sendInf("");//保证程序正常运行
if (low == "true") {
rev();//接收考试已报名提醒
sendInf("");//保证程序正常运行
return;
}
rev();//接收是否报名成功提醒
sendInf("");//保证程序正常运行
}
}
std::string kss = receiveInf();//读取kss
if (kss == "true") {
rev();//报名成功提醒
sendInf("");//保证程序正常运行
}
else {
rev();//报名失败提醒
sendInf("");//保证程序正常运行
}
}
void beginTest() {
std::string row = receiveInf();//接收row
sendInf("");//保证程序正常运行
if (row == "false") {
rev();//接收未报名考试的提醒
sendInf("");//保证程序正常运行
}
else {
rev();//当前报名考试列表的提醒
sendInf("");//保证程序正常运行
rev();//接收已报名的考试列表
sendInf("");//保证程序正常运行
rev();//获取考试序号提醒
std::string ins = SafeRead::readNum(5, "-1");
sendInf(ins);
std::string num = receiveInf();//接收考试数量
sendInf("");//保证程序正常运行
if (strToLf(ins) < 1 || strToLf(ins) > strToLf(num)) {
rev();//没有该选项提醒
sendInf("");//保证程序正常运行
}
else {
std::string have = receiveInf();//接收试卷情况
sendInf("");//保证程序正常运行
if (have == "false") {
rev();
sendInf("");//保证程序正常运行
}
else {
std::string number = receiveInf();//接收试题数量
sendInf("");//保证程序正常运行
for (int i = 0; i < strToLf(number); i++) {
rev();//收到一个试题
sendInf("");//保证程序正常运行
std::string type = receiveInf();//接收试题类型
sendInf("");//保证程序正常运行
if (type == "1") {
rev();//请输入选项提醒
sendInf(SafeRead::readString(15, "未输入"));
}
else if (type == "2") {
rev();
sendInf(SafeRead::readString(500, "未输入"));
}
else {
rev();
sendInf(SafeRead::readText(1024, "未输入"));
}
}
rev();//正在记录成绩提醒
sendInf("");//保证程序正常运行
rev();//考试成绩判断
sendInf("");//保证程序正常运行
}
}
}
}
//查看成绩
void checkResult() {
rev();//接收参加的考试列表
sendInf("");//保证程序正常运行
rev();//接收回车
sendInf("");//保证程序正常运行
rev();//接收成绩
sendInf("");//保证程序正常运行
}
//修改题目
void modifySubject() {
rev();
sendInf(SafeRead::readString(50,"未输入"));//请输入要修改试题的考试名称
std::string flags = receiveInf();//接收flags
sendInf("");//保证程序正常运行
if (flags == "false") {
rev();
sendInf("");//保证程序正常运行
}
else {
rev();//当前试卷如下提醒
sendInf("");//保证程序正常运行
rev();//接收试卷
sendInf("");//保证程序正常运行
rev();
sendInf(SafeRead::readNum(1, "1"));//请输入要修改的题目编号
rev();//请重新输入题目
sendInf("");//保证程序正常运行
while (true) {
rev();
std::string type = SafeRead::readNum(1, "1");
sendInf(type);//请输入题目类型
if (type != "1" && type != "2" && type != "3") {
rev();
sendInf("");//保证程序正常运行
continue;
}
rev();
sendInf(SafeRead::readText(1024, "未输入"));
while (true) {
rev();
std::string scores = SafeRead::readNum(4, "-1");
sendInf(scores);
if (scores.c_str()[0] == '-' || scores == "0") {
rev();
sendInf("");//保证程序正常运行
continue;
}
break;
}
if (type == "1") {
rev();
sendInf(SafeRead::readString(1, "0"));
}
else {
rev();
sendInf(SafeRead::readText(1024, "未输入"));
}
rev();
sendInf("");//保证程序正常运行
break;
}
rev();//修改成功报告
sendInf("");//保证程序正常运行
}
}
//删除题目
void deleteSubject() {
rev();
sendInf(SafeRead::readString(50, "未输入"));//请输入要删除试题的考试名称
std::string flags = receiveInf();//接收flags
sendInf("");//保证程序正常运行
if (flags == "false") {
rev();
sendInf("");//保证程序正常运行
}
else {
rev();//当前试卷如下提醒
sendInf("");//保证程序正常运行
rev();//接收试卷
sendInf("");//保证程序正常运行
rev();
sendInf(SafeRead::readNum(1, "1"));//请输入要删除的题目编号
std::cout << "删除成功\n\n";
}
}
//修改用户
void modifyUser() {
rev();
std::string order = SafeRead::readNum(1, "1");
sendInf(order);//送出身份选择
if (order == "1") {
order = "teacher";
}
else {
order = "student";
}
rev();
sendInf(SafeRead::readString(15, "未输入"));//送出要修改的账号
std::string row = receiveInf();//接收row
sendInf("");//保证程序正常运行
if (row == "false") {
rev();
sendInf("");//保证程序正常运行
}
else {
rev();
sendInf("");//保证程序正常运行
rev();//接收当前用户信息
sendInf("");//保证程序正常运行
rev();//接收当前开始修改提示信息
sendInf("");//保证程序正常运行
std::string oldInf;
oldInf = receiveInf();//接收老姓名
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readString(20, oldInf));//送出新姓名
oldInf = receiveInf();//接收老专业
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readString(20, oldInf));//送出新专业
if (order == "student") {
oldInf = receiveInf();//接收老年级
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readNum(1, oldInf));//送出新年级
oldInf = receiveInf();//接收老班级
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readNum(1, oldInf));//送出新班级
}
oldInf = receiveInf();//接收老电话
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readString(11, oldInf));//送出新电话
oldInf = receiveInf();//接收老账号
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readString(20, oldInf));//送出新账号
oldInf = receiveInf();//接收老密码
sendInf("");//保证程序正常运行
rev();//接收提示信息
sendInf(SafeRead::readString(15, oldInf));//送出新密码
rev();
sendInf("");//保证程序正常运行
}
}
//删除用户
void deleteUser() {
rev();
std::string order = SafeRead::readNum(1, "1");
sendInf(order);//送出身份选择
if (order == "1") {
order = "teacher";
}
else {
order = "student";
}
rev();
sendInf(SafeRead::readString(15, "未输入"));//送出要删除的账号
std::string row = receiveInf();//接收row
sendInf("");//保证程序正常运行
if (row == "false") {
rev();
sendInf("");//保证程序正常运行
}
else {
rev();
sendInf("");//保证程序正常运行
rev();//接收当前用户信息
sendInf("");//保证程序正常运行
rev();//接收是否删除的选择
std::string inf = SafeRead::readNum(1, "2");
sendInf(inf);//送出选择
rev();//接收报告消息
sendInf("");//保证程序正常运行
}
}
五、小结?
这次实训可谓打了我个措手不及,实训开始前两天才说要用mysql和socket。我只得紧赶慢赶肝了两天学完了mysql基础的语法,而socket则是完全没时间学,,后面完成通信时也是吃了非常大的亏,以至于压到最后时刻才勉强完成,还有很多预期的功能没有做,最后几个做完的功能也有些暴力开发的意思,没有考虑代码精简的问题,容错也不到位。
最后还是那句:如果有bug,请一定一定告诉我!感谢!!!
|