• (实训)C/S架构的考试系统(mysql + socket)


     

    首先,要完成通信至少要建2个工程,分别为服务端与客户端,这两个工程的环境配置与头文件添加都要按以下步骤进行

     一、环境配置

    先说mysql环境配置

    右键项目名称,找到属性。

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

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

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

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

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

    然后为代码添加头文件。编译后如果报错,则进行以下操作:

    进入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的语法,不过我没有细心总结 ,大家可以不看。

    1. MYSQL注释:
    2. MySQL 单行注释
    3. 1) 单行注释可以使用#注释符,#注释符后直接加注释内容。格式如下:
    4. #注释内容
    5. 2) 单行注释可以使用--注释符,--注释符后需要加一个空格,注释才能生效。格式如下:
    6. -- 注释内容
    7. #和--的区别就是:#后面直接加注释内容,而--的第 2 个破折号后需要跟一个空格符在加注释内容。
    8. MySQL 多行注释
    9. 多行注释使用/* */注释符。/*用于注释内容的开头,*/用于注释内容的结尾。多行注释格式如下:
    10. /*
    11. 第一行注释内容
    12. 第二行注释内容
    13. */
    14. MYSQL数据类型:
    15. 整数类型 字节 有符号取值范围 无符号取值范围
    16. TINYINT 1 -128~127 0~255
    17. SMALLINT 2 -32768~32767 0~65535
    18. MEDIUMINT 3 -8388608~8388607 0~16777215
    19. INT 4 -2147483648~2147483647 0~4294967295
    20. BIGINT 8 -9223372036854775808~9223372036854775807 0~18446744073709551615
    21. 整数类型的可选属性有三个:
    22. (M)
    23. 表示最低显示宽度,例如int(5),当数据宽度小于5位时在数字前面需要用字符填满宽度。该项功能要配合”ZEROFILL“使用,否则指定宽度无效。
    24. 如果设置了显示宽度,不会对插入的数据有影响,还是按照类型的实际宽度保存。从MySQL8.0.17开始,整数数据类型不推荐使用显示宽度属性。
    25. UNSIGNED
    26. 表示无符号类型。使用:INT UNSIGNED
    27. ZEROFILL
    28. 表示0填充。如果某列是ZEROFILL,那么mysql会自动为当前列添加UNSIGNED属性。
    29. 如果指定了ZEROFILL表示不够M位时,用0在左边填充,超过M位时,只要不超过数据存储范围即可。
    30. (M)必须和UNSIGNED ZEROFILL一起使用才有意义,M的值跟int所占多少存储空间没有关系,int(3),int(4)在磁盘上都是占用4个字节。
    31. 字符串类型 字节 描述及存储需求
    32. CHAR(M) M M为0~255之间的整数
    33. VARCHAR(M) M为0~65536之间的整数
    34. TINYBLOB 允许长度0~255字节
    35. BLOB 允许长度0~65535字节
    36. MEDUIMBLOB 允许长度0~167772150字节
    37. LONGBLOB 允许长度0~4294967295
    38. TINYTEXT 允许长度0~255字节
    39. TEXT 允许长度0~65535字节
    40. MEDIUMTEXT 允许长度0~167772150字节
    41. LONGTEXT 允许长度0~4294967295字节
    42. VARBINARY(M) M 允许长度0~M个字节的边长字节字符集
    43. BINARY(M) M 允许长度0~M个字节的定长字节字符集
    44. CHAR与VARCHAR类型
    45. CHAR和VARCHAR很类似,都是用来保存Mysql中较短的字符串,主要区别在于:CHAR列的长度固定为创建表时声明的长度,长度可以为从
    46. 0~255的任何值,而VARCHAR的值可以是变长字符串,长度可以指定0~65535之间的值,在检索的时候,CHAR列会删除尾部的空格而
    47. VARCHAR则保留了这些空格。
    48. ENUM类型
    49. 枚举类型,它的值范围需要在创建表时通过枚举方式显示指定,对1~255个成员的枚举需要1个字节存储,对于255~65535个成员,需要2
    50. 个字节存储,最多允许65535个成员。
    51. SET类型
    52. SET和enum非常相似,里面可以包含0~64个成员,根据成员的不同,存储上也有不同。
    53. 1~8成员的集合,占1个字节
    54. 9~16成员的集合,占2个字节
    55. 17~24成员的集合,占3个字节
    56. 25~32成员的集合,占4个字节
    57. 33~64成员的集合,占8个字节
    58. set类型一次可以选取多个成员,而ENUM则只能选一个,就相当于ENUM是单选,而set是复选。
    59. 浮点类型 占用空间 精度 精确性
    60. FLOAT 4 单精度 精确到小数点后7位小数
    61. DOUBLE 8 双精度 精确到小数点后15位小数
    62. DECIMAL 变长 高精度 精确到小数点后65位小数
    63. 数据精度说明
    64. 对于浮点数类型,在MySQL中单精度使用4个字节,双精度使用8个字节。
    65. MySQL允许使用非标准语法(其他数据库未必支持,因此如果涉及到数据迁移,则最好不要这么用):FLOAT(M,D) , DOUBLE(M,D),M称为精
    66. 度(整数+小数),D称为标度(小数)。D255,0<=D<=30。例如:定义FLOAT(5,2)的一个列可以显示-999.99~999-99,超出这个范围
    67. 会报错。FLOAT和DOUBLE类型在不知道(M,D)时,默认按照实际的精度(由实际硬件和操作系统决定)来显示。不管是否显示设置了精度(M,D)
    68. ,MySQL的处理方案如下:如果存储时,整数部分超出范围,MySQL就会报错,不允许存这样的值。如果存储时,小数点部分超出范围,则:若四
    69. 舍五入后,整数部分没有超出范围,则只是警告,但能成功操作并且四舍五入删除多余的小数位后保存。例如FLOAT(52)插入999.009,近似
    70. 结果是999.01;若四舍五入后,整数部分超出范围,则报错;
    71. 定点类型 字节数 含义
    72. DECIMAL(M,D),DEC,NUMERIC M+2字节 有效范围由M和D决定
    73. 使用 DECIMAL(M,D) 的方式表示高精度小数。其中,M被称为精度,D被称为标度。0<=M<=650<=D<=30,D5,2
    74. 的类型,表示该列取值范围是-999.99~999.99DECIMAL(M,D)的最大取值范围与DOUBLE类型一样,但是有效的数据范围是由M和D决定的。
    75. DECIMAL 的存储空间并不是固定的,由精度值M决定,总共占用的存储空间为M+2个字节。也就是说,在一些对精度要求不高的场景下,比起占用
    76. 同样字节长度的定点数,浮点数表达的数值范围可以更大一些。定点数在MySQL内部是以字符串的形式进行存储,这就决定了它一定是精准的。当
    77. DECIMAL类型不指定精度和标度时,其默认为DECIMAL(10,0),表示有10个整数位,0个小数位,其范围:-9999999999~9999999999。当数
    78. 据的精度超出了定点数类型的精度范围时,则MySQL同样会进行四舍五入处理。
    79. 二进制字符串类型 长度 长度范围 占用空间
    80. BIT(M) M 1<=M<=64 约为(M+7)/8字节
    81. 如果没有指定M,默认是1位。如果插入的是10进制的,会转为二进制插入。
    82. 在使用select命令查询字段时,可以使用bin()或hex()函数进行读取。
    83. 日期时间类型 名称 字节 日期格式 最小值 最大值
    84. YEAR 年 1 YYYY或YY 1901 2155
    85. TIME 时间 3 HH:MM:SS -838:59:59 838:59:59
    86. DATE 日期 3 YYYY-MM-DD 1000-01-01 9999-12-03
    87. DATETIME 日期时间 8 YYYY-MM-DD HH:MM:SS 1000-01-01 00:00:00 9999-12-31 23:59:59
    88. TIMESTAMP 日期时间 4 YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:00UTC 2038-01-19 03:14:07UTC
    89. 时间类型 TIME 的取值范围不是 -23:59:5923:59:59 的原因是 MySQL 设计的 TIME 类型,不光表示一天之内的时间,而且可以
    90. 用来表示一个时间间隔,这个时间间隔可以超过 24 小时。
    91. 关于 `
    92. ` 是 MySQL 的转义符,避免和 mysql 的本身的关键字冲突,只要你不在列名、表名中使用 mysql 的保留字或中文,就不需要转义。
    93. 所有的数据库都有类似的设置,不过mysql用的是`而已。通常用来说明其中的内容是数据库名、表名、字段名,不是关键字。例如:
    94. select from from table;
    95. 第一个from是字段名,最后的table表名,但是同时也是mysql关键字,这样执行的时候就会报错,所以应该使用
    96. select `from` from `table`;
    97. 当然,为了便于阅读,不建议使用关键字作为字段名、表名,同时,应该对数据库名、表名、字段名用一对儿反引号包含。
    98. []内表示可不写的内容,[]在编译时不用写
    99. 不区分大小写
    100. 纯SQL语句:
    101. DDL:
    102. 查询所有数据库: SHOW DATABASES;
    103. 查询当前数据库: SELECT DATABASE();
    104. 创建数据库: CREATE DATABASE [IF NOT EXISTS] 数据库名 [DEFAULT CHARSET 字符集] [COLLATE 排序规则];
    105. 删除数据库: DROP DATABASE [IF EXISTS] 数据库名;
    106. 使用数据库: USE 数据库名;
    107. 查询当前正在使用的数据库中的所有表: SHOW TABLES;
    108. 查询表结构: DESC 表名;
    109. 创建表: CREATE TABLE 表名(
    110. 字段1 字段1类型 [COMMENT 字段1注释],
    111. ...
    112. 字段n 字段n类型 [COMMENT 字段n注释]//最后一行无逗号
    113. )[COMMENT 表注释];
    114. 向表中添加字段(列): ALTER TABLE 表名 ADD 字段名 类型(长度) [COMMENT 注释] [约束];
    115. 修改字段(列):
    116. 修改数据类型:ALTER TABLE 表名 MODIFY 字段名 新数据类型(长度);
    117. 修改字段名和类型:ALTER TABLE 表名 CHANGE 旧字段名 新字段名 类型(长度) [COMMENT 注释] [约束];
    118. 删除字段:ALTER TABLE 表名 DROP 字段名;
    119. 修改表名:ALTER TABLE 表名 RENAME ID 新表名;
    120. 删除表:DROP TABLE [IF EXISTS] 表名;
    121. 删除并重新创建表:TRUNCATE TABLE 表名;
    122. DML:
    123. 给指定字段添加数据:INSERT INTO 表名(字段名1,字段名2...) VALUES (值1,值2...);
    124. 给全部字段添加数据:INSERT INTO 表名 VALUES(值1,值2...);
    125. 批量添加数据:INSERT INTO 表名(字段名1,字段名2...) VALUES (值1,值2...),(值1,值2...)...;
    126. INSERT INTO 表名 VALUES (值1,值2...),(值1,值2...)...;
    127. 修改数据:UPDATE 表名 SET 字段名1=值1,字段名2=值2,...[WHERE 条件];
    128. 注意:如果没有条件,代表要修改该表选中字段名下的所有数据
    129. 删除数据:DELETE FROM 表名 [WHERE 条件];
    130. * 字段列表 即:字段名1,字段名2...
    131. DQL:
    132. 查询多字段:SELECT 字段1,字段2... FROM 表名;
    133. 查询全部字段(不推荐这样写):SELECT * FROM 表名;
    134. 设置别名:SELECT 字段1 [AS 别名1],字段2 [AS 别名2]...FROM 表名;
    135. 去除重复记录:SELECT DISTINCT 字段列表 FROM 表名;
    136. 条件查询:
    137. SELECT 字段列表 FROM 表名 WHERE 条件列表;
    138. MYSQL条件类型:
    139. 比较运算符 逻辑运算符 模糊匹配 like
    140. 等于 = and 或 && %表示任意多个任意字符
    141. 大于 > or 或 || _表示一个任意字符
    142. 大于等于 >= not 或 !
    143. 小于 <
    144. 小于等于 <=
    145. 不等于 != 或 <>
    146. 范围 BETWEEN...AND... 左小于右
    147. 列表多选一 IN(...)
    148. 范围查询 空值查询
    149. in表示在一个非连续的范围内 is null
    150. not in表示不在一个非连续的范围内 is not null
    151. 查询没有学号的学生:
    152. SELECT * FROM 表名 WHERE 字段名 IS NULL;
    153. 查询长度为2的字符:
    154. select 字段列表 from 表名 where 字段名 like'__';
    155. 查询名字以汽车车结尾的产品
    156. select 字段列表 from 表名 where name like '%汽车';
    157. 查询姓商的同学:
    158. select 字段列表 from 表名 where name like '商%';
    159. 特殊的范围查询:
    160. select 字段列表 from 表名 where 字段名 between 值1 and2;
    161. 1必须小于等于值2
    162. select 字段列表 from 表名 where 字段名 in(值1,值2...);
    163. 多个条件之间用逻辑运算符链接
    164. 聚合函数:
    165. 常见聚合函数:
    166. count 统计数量 max 最大值
    167. min 最小值 avg 平均值
    168. sum 求和
    169. 求表中的数据数量:SELECT COUTN(*) FROM 表名;
    170. 求表中某字段的数据数量:SELECT COUNT(数据名) FROM 表名;
    171. 求表中某字段的平均值:SELECT AVG(字段名) FROM 表名;
    172. 求表中某字段的最大值:SELECT MAX(字段名) FROM 表名;
    173. 求所有名字叫'阿白'的学生的最小身高:SELECT MIN(height) FROM student where name = '阿白';
    174. 分组查询:
    175. SELECT 字段列表 FROM 表名 [WHERE 条件] GROUP BY 分组字段名 [HAVING 分组后过滤条件];
    176. 注意:where 与 having 的区别
    177. where 分组前过滤,不满足where条件的不参与分组
    178. having 分组后过滤,对分组结果进行过滤
    179. 查询男女人数:select gender, count(*) from emp grop by gender;
    180. 显示如下:
    181. gender `count(*)`
    182. 女 女生人数
    183. 男 男生人数
    184. 查询年龄<45岁的员工,并根据工作地址分组,获取员工数量大于等于3的工作地址
    185. select workaddress as 工作地址, count(*) as 人数 from employee where age < 45 group by 工作地址 having 人数 >= 3;
    186. 执行顺序:where > 聚合函数 > having
    187. 排序查询:
    188. SELECT 字段列表 FROM 表名 ORDER BY 字段1 排序方式1,字段2 排序方式2...;
    189. 排序方式:
    190. 升序(默认值):ASC
    191. 降序:DESC
    192. 根据年龄对公司的员工升序排序:
    193. SELECT * FROM employee order by age;
    194. 根据入职时间降序排序:
    195. select * from employee order by entryDate desc;
    196. 先按年龄升序排序,年龄相同按照入职时间降序排序:
    197. select * from employee order by age, entryDate desc;
    198. 分页查询:
    199. select 字段列表 from 表名 limit 起始索引,查询记录数;
    200. 起始索引从0开始,起始索引 = (查询页码 - 1) * 每页显示的记录数
    201. 如果查询的是第一页的数据,起始索引可省略
    202. 例:
    203. 查询第一页员工数据,每页显示10条记录:
    204. select * from empployee limit 0,10;
    205. 查询第二页员工数据,每页显示10条记录:
    206. select * from empployee limit 10,10;
    207. 查询第三页前八条员工记录,每页显示10条数据
    208. select * from employee limit 20,8;
    209. DQL编写顺序:
    210. select 字段列表 from 表名 where 条件列表 group by 分组字段列表
    211. having 分组后条件列表 order by 排序字段列表 limit 分页参数
    212. DQL执行顺序:
    213. from->where->group by->having->select->order by->limit
    214. 别名的特殊使用:
    215. select e.name , e.age from employee e where e.age > 15;
    216. DCL:
    217. 查询用户:
    218. USE mysql;
    219. select * from user;
    220. 创建用户:
    221. CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
    222. 修改用户密码:
    223. ALTER USER '用户名'@'主机名' IDENTIFIED WITH mysql_native_password BY '新密码';
    224. 删除用户
    225. DROP USER '用户名'@'主机名';
    226. 例:
    227. 创建用户 ab, 只能在当前主机(localhost)访问,密码为aaa;
    228. create user 'ab'@'localhost' identified by 'aaa';
    229. 创建用户 cd, 可以在任意主机访问,密码为bbb;
    230. create user 'cd'@'%', identified by 'bbb';
    231. 修改 ab 的密码为'ccc';
    232. alter user 'ab'@'localhost' idetified with mysql_native_password by 'ccc';
    233. 加密方式↑
    234. 权限控制:
    235. 查询权限:SHOW GRANTS FOR '用户名'@'主机名';
    236. 授予权限:GRANT 权限列表 ON 数据库名,表名 TO '用户名'@'主机名';
    237. 撤销权限:REVOKE 权限列表 ON 数据库名,表名 FROM '用户名'@'主机名';
    238. 例:
    239. grant all on employee.* to 'cd'@'%';
    240. revoke all on employee.* from 'cd'@'%';
    241. grant all *.* to 'ab'@'localhost';
    242. 函数
    243. 字符串函数:
    244. concat(s1,s2...sn)
    245. 将字符串s1~sn拼接为一个字符串
    246. lower(str)
    247. 转小写
    248. upper(str)
    249. 转大写
    250. lpad(str,n,pad)
    251. 左填充,用字符串pad填充str到长度n
    252. rpad(str,n,pad)
    253. 右填充,用字符串pad填充str到长度n
    254. trim(str)
    255. 去掉字符串头部和尾部的空格
    256. substring(str,start,len)
    257. 返回str从start起长度len的字符串,索引从1开始
    258. 例:
    259. select concat('hello', 'mysql');
    260. select lower('HEllo');
    261. select lpad('01',5,'-');
    262. select rpad('01',6,'a3b');
    263. update employee set worknumber = lpad(worknumber,5,'0');
    264. ...
    265. 数值函数:
    266. celi(x) 对x向上取整
    267. floor(x) 对x向下取整
    268. mod(x,y) 返回 x%y
    269. rand() 返回0~1内的随机数
    270. round(x,y) 求参数x的四舍五入的值,保留y位小数
    271. 例:
    272. 生成六位验证码
    273. select lpad(round(rand()*1000000, 0), 6, '0');
    274. 日期函数:
    275. curdate() 返回当前日期
    276. curtime() 返回当前时间
    277. now() 返回当前日期和时间
    278. year(date) 获取指定date的年份
    279. month(date) 获取指定date的月份
    280. day(date) 获取指定date的日期
    281. date_add(date, interval expr type)
    282. 返回一个日期/时间值加上一个时间间隔expr后的时间值
    283. datediff(date1,date2) 返回起止时间之间的天数
    284. 例:
    285. select date_add(now(), interval 70 month);
    286. select datediff('2021-10-01','2022-12-15');
    287. ...(可嵌套)
    288. 流程控制函数:
    289. if(value, t, f)
    290. 如果value为true,返回t,否则返回f
    291. ifnull(value1, value2)
    292. 如果value1不为空,返回value1,否则返回value2
    293. case when [val1] then [res1] ... else [default] end
    294. 如果val1为true,返回res1,...否则返回default默认值
    295. case [expr] when [val1] then [res1]...else [default] end;
    296. 如果expr的值等于val1,返回res1,...否则返回default默认值
    297. 例:
    298. select ifnull('', 'default'); 返回''
    299. select ifnull(null, 'default'); 返回default
    300. select
    301. id,
    302. name,
    303. (case when math >= 85 then '优秀' when math >= 60 then '及格' else '不及格' end) '数学';
    304. from score;
    305. select
    306. name,
    307. (case workaddress when '北京' then '一线' when '上海' then '一线' else '二线' end) as '工作地址'
    308. from employee;
    309. 约束
    310. 关键字 约束名 效果
    311. not null 非空约束 限制该字段数据不能为null
    312. unique 唯一约束 保证该字段所有数据都唯一,不重复
    313. primary key 主键约束 主键是一行数据的唯一标识,非空且唯一
    314. default 默认约束 保存数据时,如果未指定该字段的值,则采用默认值
    315. check 检查约束 保证字段值满足某一个条件
    316. foreign key 外键约束 用来让两张表的数据之间建立连接,保证数据的一致性和完整性
    317. 外键行为 说明
    318. no action 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有则不允许删除/更新
    319. restrict 与no action一致
    320. cascade 当在父表中删除/更新对应记录时,首先检查该记录是否有对应外键,如果有,则也删除/更新外键在字表中的记录
    321. set null 当在父表中删除对应记录时,首先检查该记录是否有对应外键,如果有则设置子表中该外键的值为null(要求外键允许取null)
    322. set default 父表有变更时,子表将外键列设置为一个默认的值
    323. 添加外键:
    324. 创建表时:
    325. create table 表名(
    326. 字段名 数据类型...
    327. ...
    328. [constraint][外键名称] foreign key (外键字段名) references 主表(主表列名)
    329. )...;
    330. 创建表后:
    331. alter table 表名 add constraint 外键名称 foreign key (外键字段名) references 主表(主表列名);
    332. 删除外键:
    333. alter table 表名 drop foreign key 外键名称;
    334. 设置外键行为:
    335. 添加外键的语法 on update 更新时的行为 on delete 删除时的行为
    336. 例:
    337. create table user( 自动增长↓
    338. id int primary key auto_increment comment '主键',
    339. name varchar(10) not null unique comment '姓名',
    340. age int check ( age > 0 && age < 120 ) comment '年龄',
    341. status char(1) default '1' comment '状态',
    342. gender char(1) comment '性别'
    343. dept_id int comment '外键约束' #之后用来链接外键
    344. )comment '用户表';
    345. alter table employee add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
    346. alter table employee drop foreign key fk_emp_dept_id;
    347. 多表查询
    348. 查看多表关系:在DG中,右键中间表,最下面选择以可视化界面展示
    349. 一对多:多的一方的外键链接一的一方的主键
    350. 多对多:建立中间表并建立两个外键,分别链接另外两表的主键
    351. 一对一(多用于拆分的表):任意一方加入外键,关联另外一方的主键,并设置外键为唯一(unique)
    352. 有效查询多个有关的表:
    353. select * from emp, dept where emp.dept_id = dept.id;
    354. 内连接:查询A,B交集的数据
    355. 隐式内连接:select 字段列表 from 表1,表2 where 条件...
    356. 显式内连接:select 字段列表 from 表1[inner] join 表2 on 连接条件...
    357. c++中的MYSQL
    358. 所需头文件
    359. #include
    360.     #include
    361. #pragma comment(lib,"libmysql.lib")
    362. #pragma comment(lib,"wsock32.lib")
    363. #pragma comment(lib, "ws2_32.lib")
    364. 一般将执行语句封入string,再通过.c_str()传入相应函数
    365. MYSQL* mysql = NULL 创建数据库对象
    366. mysql_init() 初始化数据库
    367. mysql_options() 连接设置
    368. mysql_real_connect() 连接数据库
    369. mysql_query() 传入指令
    370. mysql_store_result() 获得数据库结果集
    371. mysql_num_rows() 获得结果集中的行数
    372. mysql_num_fields() 获得结果集中的列数
    373. mysql_fetch_field() 获取列的字段名、字段类型和大小等信息
    374. mysql_fetch_row() 检索结果集的下一行
    375. mysql_free_result() 释放先前查询所储存的数据集
    376. mysql_close() 关闭当前数据库链接
    377. errorIntoMySQL() 弹出错误
    378. mysql_store_result()与 mysql_use_result():
    379. mysql_store_result()立即检索所有的行,而 mysql_use_result()启动查询,但实际上并未获取任何行,
    380. mysql_store_result()假设随后会调用 mysql_fetch_row()检索记录。这些行检索的不同方法引起两者在其
    381. 他方面的不同。本节加以比较,以便了解如何选择最适合应用程序的方法。当mysql_store_result()从服务器
    382. 上检索结果集时,就提取了行,并为之分配内存,存储到客户机中,随后调用 mysql_fetch_row()就再也不会返
    383. 回错误,因为它仅仅是把行脱离了已经保留结果集的数据结构。mysql_fetch_row()返回 NULL始终表示已经到达
    384. 结果集的末端。相反,mysql_use_result()本身不检索任何行,而只是启动一个逐行的检索,就是说必须对每行
    385. 调用 mysql_fetch_row()来自己完成。既然如此,虽然正常情况下,mysql_fetch_row()返回NULL仍然表示此
    386. 时已到达结果集的末端,但也可能表示在与服务器通信时发生错误。可通过调用mysql_errno()和mysql_error()
    387. 将两者区分开来。与mysql_use_result()相比,mysql_store_result()有着较高的内存和处理需求,因为是
    388. 在客户机上维护整个结果集,所以内存分配和创建数据结构的耗费是非常巨大的,要冒着溢出内存的危险来检索大型
    389. 结果集,如果想一次检索多个行,可用 mysql_use_result()。mysql_use_result()有着较低的内存需求,因为
    390. 只需给每次处理的单行分配足够的空间。这样速度就较快,因为不必为结果集建立复杂的数据结构。另一方面,
    391. mysql_use_result()把较大的负载加到了服务器上,它必须保留结果集中的行,直到客户机看起来适合检索所有的
    392. 行。这就使某些类型的客户机程序不适用mysql_use_result():
    393. c++中的TCP
    394. WSAData wsaData: 存放windows socket初始化信息
    395. WSAStartup: 使库文件与当前的应用程序绑定,以调用该版本的socket的各种函数
    396. 原型:int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
    397. 参数:wVersionRequested是Windows Sockets API提供的调用方可使用的最高版本号。高位字节指出
    398. 副版本(修正)号,低位字节指明主版本号。lpWSAData 是指向WSADATA数据结构的指针,用来接收
    399. Windows Sockets实现的细节。
    400. 返回值:返回0则执行成功。
    401. word类型:储存socket编程中的版本信息
    402. makeword():创建word类型。
    403. LOBYTE(): 取 16 进制数的最低字节
    404. HIBYTE(): 取 16 进制数的最高字节
    405. //这俩的返回值不用管,照着写就行,没查到,老师说是默认(
    406. WSACleanup(): 清理,成功返回0,可用WSAGetLastError来获取错误码。
    407. 注意:
    408. 当调用了WSACleanup,在此进程中任何挂起的或者异步的套接字调用都会取消,而且不会发出通知消息也不会设置事件对象。
    409. 为了使挂起的数据发送出去,应用程序应该使用shutdown来关闭连接,然后一直等待关闭完成再调用closesocket和WSACleanup。
    410. 和WSAStartup一样,WSACleanup也不能在DllMain中调用(可能会死锁)。
    411. SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, 0):
    412. 建立一个协议族为AF_INET、协议类型SOCK_STREAM、协议编号为0的套接字
    413. AF_UNIX(本机通信)
    414. AF_INET(TCP/IP – IPv4)
    415. AF_INET6(TCP/IP – IPv6)
    416. SOCK_STREAM(TCP流)
    417. SOCK_DGRAM(UDP数据报)
    418. SOCK_RAW(原始套接字)
    419. INVALID_SOCKET: 表示该 socket fd 无效。(判断正误)
    420. sockaddr_in:internet环境下套接字的地址形式
    421. htonl:把本机字节顺序转化为网络字节顺序
    422. h:host 本地主机
    423. to:to
    424. n:net 网络的意思
    425. l:unsigned long
    426. INADDR_ANY:监听0.0.0.0地址
    427. bind():给socket绑定端口号与具体位置
    428. 参数 1:需要绑定的socket。
    429.    参数 2:存放了服务端用于通信的地址和端口。
    430.    参数3:表示 addr 结构体的大小
    431.    返回值:成功则返回0 ,失败返回-1,错误原因存于 errno 中。如果绑定的
    432. 地址错误,或者端口已被占用,bind 函数一定会报错,否则一般不会返回错误。
    433. sockaddr:一种通用的套接字地址
    434. CONNECT_NUM_MAX:(没搜到这个宏)
    435. sockaddr_in:internet环境下套接字的地址形式
    436. accept():接收一个套接字中已建立的连接
    437. 参数1:利用系统调用socket()建立的套接字描述符,通过bind()绑定到一个本地地址(一般为服务器的套接字),并且通过listen()一直在监听连接;
    438. 参数2:指向struct sockaddr的指针,该结构用通讯层服务器对等套接字的地址(一般为客户端地址)填写,返回地址addr的确切格式由套接字的地址
    439. 类别(比如TCP或UDP)决定;若addr为NULL,没有有效地址填写,这种情况下,addrlen也不使用,应该置为NULL
    440. 参数3:一个值结果参数,调用函数必须初始化为包含addr所指向结构大小的数值,函数返回时包含对等地址(一般为服务器地址)的实际数值;
    441. recv(): 从连接的套接字或绑定的无连接套接字接收数据
    442. 参数1:指定接收端套接字描述符;
    443. 参数2:指明一个缓冲区,该缓冲区用来存放recv函数接收到的数据;
    444. 参数3:指明buf的长度;
    445. 参数4:一般置0
    446. 返回值:<0 出错; =0 连接关闭; >0 接收到数据大小
    447. send():将我们的数据复制黏贴进系统的协议发送缓冲区,计算机伺机发送出去
    448. 参数1:标识已连接套接字的描述符。
    449. 参数2:指向包含要传输的数据的缓冲区的指针。
    450. 参数3:buf参数指向的缓冲区中数据的长度(以字节为单位)。
    451. 参数4:一组标志,指定进行呼叫的方式。 通过将按位或运算符与以下任何值一起使用来构造此参数。
    452. 返回值:成功返回写入的字节数;执行失败,返回SOCKET_ERROR
    453. closesocket():关闭一个套接口

    三、头文件添加

    下面是代码。代码分为三部分 服务端,客户端,还有一个我自己定义的stdafx头文件。这个头文件是vs库自带的。我的出于某些原因没有。当然,如果你有的话,将stdafx头文件放在最上方,下方添加以下头文件:

    1. #include
    2. #include
    3. #include
    4. #pragma comment(lib,"libmysql.lib")
    5. #pragma comment(lib,"wsock32.lib")
    6. #pragma comment(lib,"ws2_32.lib")
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include

    如果不知道头文件如何创建:

     

    刚创好的头文件会自带一行#pragma once。自定义中写过了,覆盖即可。

    自定义的stdafx头文件内容:

    1. // stdafx.h : include file for standard system include files,
    2. // or project specific include files that are used frequently, but
    3. // are changed infrequently
    4. //
    5. #if !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)
    6. #define AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_
    7. #if _MSC_VER > 1000
    8. #pragma once
    9. #endif // _MSC_VER > 1000
    10. // Insert your headers here
    11. #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
    12. #define DLLEXPORT __declspec(dllexport)
    13. #define DLLIMPORT __declspec(dllimport)
    14. #include
    15. #include
    16. #include
    17. #pragma comment(lib,"libmysql.lib")
    18. #pragma comment(lib,"wsock32.lib")
    19. #pragma comment(lib,"ws2_32.lib")
    20. #include
    21. #include
    22. #include
    23. #include
    24. #include
    25. #include
    26. #include
    27. #include
    28. #include
    29. // TODO: reference additional headers your program requires here
    30. void Msg(char* szFormat, ...);
    31. void dbMsg(char* szFormat, ...);
    32. //{{AFX_INSERT_LOCATION}}
    33. // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
    34. #endif // !defined(AFX_STDAFX_H__4607A810_33E2_483D_80D8_BE41F0D473D5__INCLUDED_)

    需要注意的是,这个头文件服务端,客户端两个工程都需要添加

    四、服务端与客户端的创建 

    先说明很重要的一点。安装好后每个人都设置了自己的mysql账号和密码。在我的代码中我会将他们删去,如果想使用这份代码,那么需要添上自己的。代码具体位置在服务端的1467行左右:

     涂黑的,左边是账号,右边是密码。

     1.服务端的创建:

    别忘了自定义头文件stdafx或者按照上面已有stdafx的情况添加我列出的头文件

    代码:

    1. #include "stdafx.h"
    2. WSADATA localWsaData;
    3. SOCKET connectSocket;
    4. SOCKET serverSocket;
    5. HANDLE hMUTEX;
    6. int sendInf(std::string sendBuff) {
    7. sendBuff += '\0';
    8. if (sendBuff == "#") {
    9. sendBuff = "system: 服务器端请求终止对话...\n";
    10. closesocket(serverSocket);
    11. WSACleanup();
    12. return 0;
    13. }
    14. if (send(connectSocket, sendBuff.c_str(), sizeof(char) * sendBuff.size(), 0) == SOCKET_ERROR) {
    15. std::cout << "system: 发送连接消息失败: " << WSAGetLastError() << std::endl;
    16. closesocket(serverSocket);
    17. WSACleanup();
    18. return -1;
    19. }
    20. return 1;
    21. }
    22. std::string receiveInf() {
    23. char recvBuff[1024]{};
    24. if (recv(connectSocket, recvBuff, 1024, 0) == SOCKET_ERROR) {
    25. std::cout << "system: 接收连接消息失败: " << WSAGetLastError() << std::endl;
    26. closesocket(serverSocket);
    27. WSACleanup();
    28. return "";
    29. }
    30. return recvBuff;
    31. }
    32. //便捷读取
    33. class SafeRead
    34. {
    35. public:
    36. //录入数字
    37. static std::string readNum(int length, const std::string& oldNum) {
    38. std::string inf;
    39. //label位置
    40. label:while (true) {
    41. std::cout << " 请输入数字:";
    42. getline(std::cin, inf);
    43. if (inf == "\n" || inf.empty()) {
    44. return oldNum;
    45. }
    46. else if ((int)inf.length() > length) {
    47. std::cout << "\n\t长度超过" << length << "位(计算需要包含小数点),请重新输入。\n";
    48. continue;
    49. }
    50. std::stringstream sin(inf);
    51. double d;
    52. char c;
    53. bool flag = true;
    54. if (!(sin >> d))
    55. flag = false;
    56. if (sin >> c)
    57. flag = false;
    58. if (!flag) {
    59. std::cout << "输入的不是一个数字,请重新输入" << std::endl;
    60. continue;
    61. }
    62. break;
    63. }
    64. //删除前导零
    65. std::string::iterator it = inf.begin();
    66. for (unsigned int i = 0; i < inf.length() - 1; i++) {//单0不删,一串0只留一个
    67. if (inf[i] == '-') continue;
    68. if (inf[i] != '0') break;
    69. if (inf[i] == '0' && inf[i + 1] == '.') break;
    70. inf.erase(it);
    71. it++;
    72. }
    73. return inf;
    74. }
    75. //录入有限制的字符串,用于读取基本信息
    76. static std::string readString(int length, std::string old) {
    77. std::string inf;
    78. while (true) {
    79. getline(std::cin, inf);
    80. if (inf == "\n" || inf.empty()) {
    81. return old;
    82. }
    83. else if ((int)inf.length() > length) {
    84. std::cout << "\n\t信息长度超过" << length << ",请重新输入。\n";
    85. continue;
    86. }
    87. return inf;
    88. }
    89. }
    90. //读取文本块,以~~~结束
    91. static std::string readText(int length, std::string old) {
    92. while (true) {
    93. std::string ans;
    94. while (true) {
    95. std::string inf;
    96. getline(std::cin, inf);
    97. if (inf == "~~~") {
    98. break;
    99. }
    100. else {
    101. ans = ans + inf + "\n";
    102. }
    103. }
    104. if (ans.size() > length) {
    105. std::cout << "当前文本长度(包括空格)为 " << ans.size() << ",已超过限定长度 " << length << ",请重新输入..." << std::endl;
    106. continue;
    107. }
    108. return ans;
    109. }
    110. }
    111. };
    112. //double转string函数
    113. std::string lfToStr(double num)
    114. {
    115. std::stringstream ss;
    116. std::string str;
    117. ss << num;
    118. ss >> str;
    119. return str;
    120. }
    121. //string转换为double函数
    122. double strToLf(const std::string& number) {
    123. double lf = 0, lfi = 0, x = 10;
    124. int i = 0, f = 1, times = 1, length = (int)number.length();
    125. while (number[i] < '0' || number[i] > '9') {//跳过可能存在的¥,$ 或 -
    126. i++;
    127. if (number[i] == '-')
    128. f *= -1;
    129. }
    130. //整数位
    131. while (i < length) {
    132. if (number[i] == '.') {
    133. break;
    134. }
    135. lf = lf * 10 + number[i] - '0';
    136. i++;
    137. }
    138. //小数位,++i跳过‘ . ’
    139. while (++i < length) {
    140. lfi += (number[i] - '0') / x;
    141. x *= 10;
    142. }
    143. return times * f * (lf + lfi);
    144. }
    145. //创建不重复的随机数组
    146. std::vector<int> createRandList(int left, int right) {
    147. int length = right - left + 1;
    148. std::default_random_engine start;
    149. std::uniform_int_distribution<int> getRand(left, right);
    150. start.seed(time(0));
    151. std::unordered_set<int> list;
    152. while (list.size() < length) {
    153. list.insert(getRand(start));
    154. }
    155. std::vector<int> randomSunject(list.begin(), list.end());
    156. return randomSunject;
    157. }
    158. MYSQL localMysql;
    159. //mysql c++的使用
    160. class MysqlOperation {
    161. public:
    162. //封装query函数
    163. static bool useQuery(MYSQL* mysql, std::string instruction) {
    164. int res = mysql_query(mysql, instruction.c_str());
    165. if (res) {
    166. std::cout << mysql_error(mysql) << std::endl;
    167. return false;
    168. }
    169. else {
    170. return true;
    171. }
    172. }
    173. //基础的搜索框架,返回处理过的string型结果集
    174. static std::string basicSelect(MYSQL* mysql) {
    175. MYSQL_RES* result = mysql_store_result(mysql);
    176. int column = mysql_num_fields(result);
    177. std::string ans;
    178. MYSQL_ROW row = mysql_fetch_row(result);
    179. while (row) {
    180. for (int i = 0; i < column; i++) {
    181. if (row[i]) {
    182. ans += row[i];
    183. }
    184. else {
    185. ans += "null";
    186. }
    187. if (i < column - 1) {
    188. ans += "\t";
    189. }
    190. }
    191. row = mysql_fetch_row(result);
    192. if (row) {
    193. ans += "\n";
    194. }
    195. }
    196. mysql_free_result(result);
    197. return ans;
    198. }
    199. //连接数据库
    200. static bool ConnectDB(std::string host, std::string user, std::string password, std::string DBname, int port)
    201. {
    202. MYSQL* mysql = mysql_init(&localMysql);//初始化localMysql
    203. if (!mysql) {
    204. std::cout << mysql_error(mysql) << std::endl;
    205. return false;
    206. }
    207. mysql_options(&localMysql, MYSQL_SET_CHARSET_NAME, "GBK");
    208. mysql = mysql_real_connect(&localMysql, host.c_str(), user.c_str(), password.c_str(), DBname.c_str(), port, NULL, 0);
    209. if (mysql == nullptr) {
    210. std::cout << mysql_error(mysql) << std::endl;
    211. return false;
    212. }
    213. std::cout << "连接mysql成功!\n";//连接成功反馈
    214. std::string DBName = "ExaminationSystem";
    215. createDatabase(DBName);
    216. bool res = useQuery(&localMysql, "use ExaminationSystem");
    217. if (res) {
    218. std::cout << "已转到数据库\"ExaminationSystem\"" << std::endl;
    219. }
    220. return res;
    221. }
    222. //创建数据库
    223. static bool createDatabase(std::string& DBName)
    224. {
    225. std::string oper = "create database if not exists " + DBName;
    226. bool res = useQuery(&localMysql, oper);
    227. if (res) {
    228. std::cout << "\"" << DBName << "\"数据库创建成功或已存在" << std::endl;
    229. }
    230. return res;
    231. }
    232. //更改使用的数据库
    233. static bool changeUsingBase(std::string DBName) {
    234. std::string oper = "use " + DBName;
    235. bool res = useQuery(&localMysql, oper);
    236. if (res) {
    237. std::cout << "数据库使用情况已更改,当前使用的数据库为:\"" + DBName + "\"" << std::endl;
    238. }
    239. return res;
    240. }
    241. //查看连接状态
    242. static bool checkIfConnectDB() {
    243. MYSQL* mysql = &localMysql;
    244. int res = mysql_query(mysql, "select database()");
    245. if (res) {
    246. std::cout << mysql_error(mysql) << std::endl;
    247. return false;
    248. }
    249. MYSQL_RES* result = mysql_store_result(mysql);
    250. MYSQL_ROW line = mysql_fetch_row(result);
    251. if (!line) {
    252. std::cout << "未连接任何数据库" << std::endl;
    253. return false;
    254. }
    255. else {
    256. std::cout << "数据库连接状态:已连接\n" << "连接的数据库为:" << line[0] << std::endl;
    257. return true;
    258. }
    259. }
    260. //删除数据库
    261. static bool deleteDataBase(std::string DBName) {
    262. for (auto iter = DBName.begin(); iter != DBName.end(); iter++) {//去除空格
    263. if (isblank(*iter) != 0) {
    264. DBName.erase(iter--);
    265. }
    266. }
    267. std::transform(DBName.begin(), DBName.end(), DBName.begin(), ::tolower);//转小写
    268. if (DBName == "mysql" || DBName == "sys" || DBName == "information_schema"
    269. || DBName == "performance_schema" || DBName == "serverobjects") {
    270. std::cout << "该库不可删除!!";
    271. }
    272. mysql_close(&localMysql);
    273. mysql_init(&localMysql);
    274. std::string oper = "drop database " + DBName;
    275. bool res = useQuery(&localMysql, oper);
    276. return res;
    277. }
    278. //查看所有表
    279. static bool checkAllTable(std::string DBName) {
    280. bool res = useQuery(&localMysql, "show tables");
    281. return res;
    282. }
    283. //创建表
    284. static bool createTable(std::string tableName, std::string basicField, std::string fieldType, std::string key, std::string autoIncrement, std::string fieldComment, std::string tableComment = "") {
    285. std::string oper = "create table if not exists `" + tableName + "` (`" + basicField + "` " + fieldType + " " + key
    286. + " " + autoIncrement + " comment '" + fieldComment + "')comment'" + tableComment + "'";
    287. bool res = useQuery(&localMysql, oper.c_str());
    288. return res;
    289. }
    290. //修改表名
    291. static bool changeTableName(std::string tableName, std::string newTableName) {
    292. std::string oper = "alter table `" + tableName + "` rename id `" + newTableName + "`";
    293. bool res = useQuery(&localMysql, oper.c_str());
    294. return res;
    295. }
    296. //删除表
    297. static bool deleteTable(std::string tableName) {
    298. MYSQL* mysql = &localMysql;
    299. std::string oper = "drop table if exists`" + tableName + "`";
    300. bool res = useQuery(mysql, oper.c_str());
    301. return res;
    302. }
    303. //查看表结构:
    304. static bool checkTableStructure(std::string tableName) {
    305. MYSQL* mysql = &localMysql;
    306. std::string oper = "desc `" + tableName + "`";
    307. bool res = useQuery(mysql, oper.c_str());
    308. if (res) {
    309. MYSQL_RES* result = mysql_store_result(mysql);
    310. int row = mysql_num_rows(result);
    311. int column = mysql_num_fields(result);
    312. MYSQL_ROW line = mysql_fetch_row(result);
    313. std::string answer = "Field\tType\tNull\tKey\tDefault\tExtra\n";
    314. while (line) {
    315. for (int i = 0; i < column; i++) {
    316. if (i) {
    317. answer += "\t";
    318. }
    319. if (line[i]) {
    320. answer += line[i];
    321. }
    322. else {
    323. answer += "null";
    324. }
    325. }
    326. answer += "\n";
    327. line = mysql_fetch_row(result);
    328. }
    329. std::cout << answer << std::endl;
    330. mysql_free_result(result);
    331. }
    332. return true;
    333. }
    334. //添加字段
    335. static bool addField(std::string tableName, std::string fieldName, std::string fieldType, std::string key, std::string autoIncrement, std::string fieldComment) {
    336. MYSQL* mysql = &localMysql;
    337. std::string oper = "alter table `" + tableName + "` add `" + fieldName + "` " + fieldType + " " + key
    338. + " " + autoIncrement + " comment '" + fieldComment + "' ";
    339. bool res = useQuery(mysql, oper.c_str());
    340. return res;
    341. }
    342. //修改字段数据类型
    343. static bool modifyFieldDataType(std::string tableName, std::string fieldName, std::string newDataType) {
    344. MYSQL* mysql = &localMysql;
    345. std::string oper = "alter table `" + tableName + "` modify `" + fieldName + "` " + newDataType;
    346. bool res = useQuery(mysql, oper.c_str());
    347. return res;
    348. }
    349. //修改字段名和类型
    350. static bool changeFieldNameDataType(std::string tableName, std::string fieldName, std::string newFieldName, std::string newDataType) {
    351. MYSQL* mysql = &localMysql;
    352. std::string oper = "alter table `" + tableName + "`change `" + fieldName + "` `" + newFieldName + "` " + newDataType;
    353. bool res = useQuery(mysql, oper.c_str());
    354. return res;
    355. }
    356. //删除字段
    357. static bool deleteField(std::string tableName, std::string fieldName) {
    358. MYSQL* mysql = &localMysql;
    359. std::string oper = "alter table `" + tableName + "` drop `" + fieldName + "`";
    360. bool res = useQuery(mysql, oper.c_str());
    361. return res;
    362. }
    363. //添加数据
    364. static bool addData(std::string tableName, std::vectorfieldList, std::vector> dataList) {
    365. std::string oper = "insert into `" + tableName + "`";
    366. std::string FL, DL;
    367. if (!fieldList.empty()) {//收集字段名
    368. FL = " ( ";
    369. for (int i = 0; i < fieldList.size(); i++) {
    370. FL = FL + "`" + fieldList[i] + "`";
    371. if (i < fieldList.size() - 1) {
    372. FL += ", ";
    373. }
    374. }
    375. FL += " ) ";
    376. }
    377. if (!dataList.empty()) {//收集要添加的数据
    378. DL = " values ";
    379. for (int i = 0; i < dataList.size(); i++) {
    380. if (!dataList[i].empty()) {
    381. DL += " ( ";
    382. for (int j = 0; j < dataList[i].size(); j++) {
    383. DL = DL + "'" + dataList[i][j] + "'";
    384. if (j < dataList[i].size() - 1) {
    385. DL += ", ";
    386. }
    387. }
    388. DL += " ) ";
    389. }
    390. if (i < dataList.size() - 1) {
    391. DL += ", ";
    392. }
    393. }
    394. }
    395. oper = oper + FL + DL;
    396. bool res = useQuery(&localMysql, oper.c_str());
    397. return res;
    398. }
    399. //修改数据
    400. static bool modifyData(std::string tableName, std::vectorfieldList, std::vectordataList, std::string condition) {
    401. if (fieldList.size() != dataList.size()) {
    402. std::cout << "字段个数数与相对应的值的个数不符! 字段有 " << fieldList.size() << " 个, 值有 " << dataList.size() << " 个。" << std::endl;
    403. return false;
    404. }
    405. std::string oper = "update `" + tableName + "` set ";
    406. for (int i = 0; i < fieldList.size(); i++) {
    407. std::string tmp;
    408. tmp = "`" + fieldList[i] + "` = " + dataList[i];
    409. if (i < fieldList.size() - 1) {
    410. tmp += ", ";
    411. }
    412. oper += tmp;
    413. }
    414. if (condition != "") {
    415. oper = oper + " where " + condition;
    416. }
    417. bool res = useQuery(&localMysql, oper);
    418. return res;
    419. }
    420. //删除数据
    421. static bool deleteData(std::string tableName, std::string condition) {
    422. std::string oper = "delete from `" + tableName + "` ";
    423. if (condition != "") {
    424. oper = oper + "where " + condition;
    425. }
    426. bool res = useQuery(&localMysql, oper);
    427. return res;
    428. }
    429. //搜索函数及其重载
    430. static bool selectTable(std::vector fieldList, std::string tableName, std::string condition, std::vector> sortList) {
    431. MYSQL* mysql = &localMysql;
    432. std::string oper = "select ";
    433. for (int i = 0; i < fieldList.size(); i++) {
    434. oper = oper + "`" + fieldList[i] + "`";
    435. if (i < fieldList.size() - 1) {
    436. oper += ", ";
    437. }
    438. }
    439. oper = oper + " from `" + tableName + "`";
    440. if (!condition.empty()) {
    441. oper += condition;
    442. }
    443. if (!sortList.empty()) {
    444. oper += " order by ";
    445. for (int i = 0; i < sortList.size(); i++) {
    446. oper = oper + "`" + sortList[i].first + "` " + sortList[i].second;
    447. if (i < sortList.size() - 1) {
    448. oper += ", ";
    449. }
    450. }
    451. }
    452. bool res = useQuery(mysql, oper);
    453. if (res) {
    454. std::string ans;
    455. for (int i = 0; i < fieldList.size(); i++) {
    456. ans += fieldList[i];
    457. if (i < fieldList.size() - 1) {
    458. ans += "\t";
    459. }
    460. }
    461. ans = ans + "\n" + basicSelect(mysql);
    462. std::cout << ans << std::endl;
    463. }
    464. }
    465. static bool selectTable(std::vector fieldList, std::string tableName, std::string condition, std::string gropField, std::string gropCondition, std::vector> sortList, std::pair paging) {
    466. MYSQL* mysql = &localMysql;
    467. std::string oper = "select ";
    468. for (int i = 0; i < fieldList.size(); i++) {
    469. oper = oper + "`" + fieldList[i] + "`";
    470. if (i < fieldList.size() - 1) {
    471. oper += ", ";
    472. }
    473. }
    474. oper = oper + " from `" + tableName + "`";
    475. if (!condition.empty()) {
    476. oper += condition;
    477. }
    478. if (!gropField.empty()) {
    479. oper = oper + " group by " + gropField;
    480. if (!gropCondition.empty()) {
    481. oper = oper + " having " + gropCondition;
    482. }
    483. }
    484. if (!sortList.empty()) {
    485. oper += " order by ";
    486. for (int i = 0; i < sortList.size(); i++) {
    487. oper = oper + "`" + sortList[i].first + "` " + sortList[i].second;
    488. if (i < sortList.size() - 1) {
    489. oper += ", ";
    490. }
    491. }
    492. }
    493. if (!(paging.first == "0" && paging.second == "0")) {
    494. oper = oper + " limit " + paging.first + ", " + paging.second;
    495. }
    496. bool res = useQuery(mysql, oper);
    497. if (res) {
    498. std::string ans;
    499. for (int i = 0; i < fieldList.size(); i++) {
    500. ans += fieldList[i];
    501. if (i < fieldList.size() - 1) {
    502. ans += "\t";
    503. }
    504. }
    505. ans = ans + "\n" + basicSelect(mysql);
    506. std::cout << ans << std::endl;
    507. }
    508. }
    509. //添加外键 功能不必要,暂时停止开发
    510. /*static bool addForeignKey(std::string foreignTable, std::string foreighName, std::string foreighFieldName, std::string mainTable, std::string mainFieldName) {
    511. MYSQL* mysql = &localMysql;
    512. std::string oper = "alter table `" + foreignTable + "` add constraint `" + foreighName + "` foreign key " + ""
    513. }*/
    514. };
    515. class Test {
    516. public:
    517. //设置考试
    518. static void setTest() {
    519. std::vectordataList;
    520. sendInf("请输入考试科目: ");
    521. dataList.push_back(receiveInf());//string 50
    522. sendInf("请输入考试分值: ");
    523. dataList.push_back(receiveInf());//int 5
    524. sendInf("请输入考试时间表,可换行。结束时另起一行输入 ~~~ 结束:\n");
    525. dataList.push_back(receiveInf());//text 500
    526. bool res = MysqlOperation::addData("subject", std::vector{"subName", "fullScore", "time"}, std::vector>{dataList});
    527. if (res) sendInf("true");
    528. else sendInf("false");
    529. receiveInf();//保证程序正常运行
    530. if (res) {
    531. MysqlOperation::createTable(dataList[0], "id", "int", "", "", "", "");
    532. MysqlOperation::addField(dataList[0], "studentName", "varchar(20)", "", "", "");
    533. MysqlOperation::addField(dataList[0], "studentMajor", "varchar(20)", "", "", "");
    534. MysqlOperation::addField(dataList[0], "studentGrade", "int", "", "", "");
    535. MysqlOperation::addField(dataList[0], "studentClass", "int", "", "", "");
    536. MysqlOperation::addField(dataList[0], "studentAccont", "varchar(20)", "", "", "");
    537. MysqlOperation::addField(dataList[0], "score", "double", "", "", "");
    538. sendInf("设置成功!");
    539. receiveInf();//保证程序正常运行
    540. }
    541. }
    542. //创建试卷
    543. static void createTest() {
    544. MYSQL* mysql = &localMysql;
    545. sendInf("请输入考试科目:");
    546. std::string testName = receiveInf();//string 50
    547. std::string oper = "select subName from `subject` where subName = '" + testName + "'";
    548. bool res = MysqlOperation::useQuery(mysql, oper);
    549. std::string test;
    550. if (res) sendInf("true");
    551. else sendInf("false");
    552. receiveInf();//保证程序正常运行
    553. if (res) {
    554. test = MysqlOperation::basicSelect(mysql);
    555. bool ress = test.empty();
    556. if (ress) sendInf("true");
    557. else sendInf("false");
    558. receiveInf();//保证程序正常运行
    559. if (ress) {
    560. sendInf("未找到该科目的考试信息,是否先设置考试? 1:现在设置 2: 暂时不用\n请输入选择:");
    561. std::string low = receiveInf();//num 1 de 2
    562. if (low == "1") {
    563. setTest();
    564. }
    565. else {
    566. return;
    567. }
    568. }
    569. else {
    570. bool res1 = MysqlOperation::createTable(testName + "test", "id", "int", "primary key", "auto_increment", "序号");
    571. bool res2 = MysqlOperation::addField(testName + "test", "type", "varchar(20)", "", "", "题目类型");
    572. bool res3 = MysqlOperation::addField(testName + "test", "topic", "varchar(1024)", "", "", "题目内容");
    573. bool res4 = MysqlOperation::addField(testName + "test", "score", "double", "", "", "分值");
    574. bool res5 = MysqlOperation::addField(testName + "test", "answer", "varchar(1024)", "", "", "答案");
    575. addSubject(testName + "test");
    576. }
    577. }
    578. }
    579. //添加试题
    580. static void addSubject(std::string test) {
    581. sendInf("请开始添加题目:\n");
    582. receiveInf();//保证程序正常运行
    583. std::vector> testList;
    584. while (true) {
    585. std::vector testEdit;
    586. sendInf("请选择题目类型,输入4退出添加题目: 1 选择题 2 填空题 3 大题: ");
    587. std::string type = receiveInf();//num 1 de 0
    588. if (type == "4") {
    589. break;
    590. }
    591. if (type != "1" && type != "2" && type != "3") {
    592. sendInf("暂不支持其他选项!\n");
    593. receiveInf();//保证程序正常运行
    594. continue;
    595. }
    596. testEdit.push_back(type);
    597. std::string inf;
    598. sendInf("请输入题目内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
    599. testEdit.push_back(receiveInf());//text 1024 de 未输入
    600. while (true) {
    601. sendInf("请输入分值: ");
    602. inf = receiveInf();//num 4 de -1
    603. if (inf.c_str()[0] == '-' || inf == "0") {
    604. sendInf("题目分值必须大于0,请重新设置!\n");
    605. receiveInf();
    606. continue;
    607. }
    608. break;
    609. }
    610. testEdit.push_back(inf);
    611. if (type == "1") {
    612. sendInf("请输入答案选项: ");
    613. inf = receiveInf();//string 10 de 0
    614. std::transform(inf.begin(), inf.end(), inf.begin(), ::toupper);
    615. testEdit.push_back(inf);
    616. }
    617. else {
    618. sendInf("请输入答案内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
    619. testEdit.push_back(receiveInf());//text 1024 未输入
    620. }
    621. testList.push_back(testEdit);
    622. sendInf("\n");
    623. receiveInf();//保证程序正常运行
    624. }
    625. std::vector fieldList = { "type", "topic", "score", "answer" };
    626. MysqlOperation::addData(test, fieldList, testList);
    627. }
    628. //修改试题
    629. static void modifySubject() {
    630. MYSQL* mysql = &localMysql;
    631. sendInf("请输入要修改删除试题的考试名称: ");
    632. std::string subName = receiveInf();
    633. MysqlOperation::useQuery(mysql, "show tables");
    634. MYSQL_RES* result = mysql_store_result(mysql);
    635. MYSQL_ROW row;
    636. bool flags = false;
    637. while (row = mysql_fetch_row(result)) {
    638. if (row[0] == subName) {
    639. flags = true;
    640. break;
    641. }
    642. }
    643. mysql_free_result(result);
    644. if (!flags) {
    645. sendInf("false");
    646. }
    647. else {
    648. sendInf("true");
    649. }
    650. receiveInf();//保证程序正常运行
    651. if (!flags) {
    652. sendInf("没有该科目试卷");
    653. receiveInf();//保证程序正常运行
    654. }
    655. else {
    656. sendInf("当前试卷如下\n");
    657. receiveInf();//保证程序正常运行
    658. MysqlOperation::useQuery(mysql, "select * from `" + subName + "test`");
    659. result = mysql_store_result(mysql);
    660. int rnum = mysql_num_fields(result);
    661. std::string ans;
    662. while (row = mysql_fetch_row(result)) {
    663. for (int i = 0; i < rnum; i++) {
    664. if (i == 0) ans += "序号:";
    665. if (i == 1) {
    666. std::string ri = row[i];
    667. if (ri == "1") {
    668. ans += "类型:选择 代号:";
    669. }
    670. else if (ri == "2") {
    671. ans += "类型:填空 代号:";
    672. }
    673. else if (ri == "3") {
    674. ans += "类型:大题 代号:";
    675. }
    676. }
    677. else if (i == 2) ans += "题目:\n";
    678. else if (i == 3) ans += "分值:";
    679. else if (i == 4) ans += "答案:";
    680. ans += row[i];
    681. ans += "\n";
    682. }
    683. ans += "\n";
    684. }
    685. sendInf(ans);//送出试卷
    686. receiveInf();//保证程序正常运行
    687. sendInf("请选择要修改的题目编号");
    688. std::string number = receiveInf();//保证程序正常运行
    689. sendInf("请重新输入题目:");
    690. receiveInf();//保证程序正常运行
    691. std::vector testEdit;
    692. while (true) {
    693. sendInf("请选择题目类型: 1 选择题 2 填空题 3 大题: ");
    694. std::string type = receiveInf();//num 1 de 0
    695. if (type != "1" && type != "2" && type != "3") {
    696. sendInf("暂不支持其他选项!\n");
    697. receiveInf();//保证程序正常运行
    698. continue;
    699. }
    700. testEdit.push_back(type);
    701. std::string inf;
    702. sendInf("请输入题目内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
    703. testEdit.push_back(receiveInf());//text 1024 de 未输入
    704. while (true) {
    705. sendInf("请输入分值: ");
    706. inf = receiveInf();//num 4 de -1
    707. if (inf.c_str()[0] == '-' || inf == "0") {
    708. sendInf("题目分值必须大于0,请重新设置!\n");
    709. receiveInf();
    710. continue;
    711. }
    712. break;
    713. }
    714. testEdit.push_back(inf);
    715. if (type == "1") {
    716. sendInf("请输入答案选项: ");
    717. inf = receiveInf();//string 1 de 0
    718. std::transform(inf.begin(), inf.end(), inf.begin(), ::toupper);
    719. testEdit.push_back(inf);
    720. }
    721. else {
    722. sendInf("请输入答案内容,可换行。结束时另起一行输入 ~~~ 结束:\n");
    723. testEdit.push_back(receiveInf());//text 1024 未输入
    724. }
    725. sendInf("\n");
    726. receiveInf();//保证程序正常运行
    727. break;
    728. }
    729. MysqlOperation::useQuery(mysql, "update `" + subName + "test` set type = '" + testEdit[0] + "', topic = '" + testEdit[1] + "', score = '" + testEdit[2] + "', answer = '" + testEdit[3] + "' where `id` = '" + number + "'");
    730. sendInf("修改成功");
    731. receiveInf();//保证程序正常运行
    732. }
    733. }
    734. //删除题目
    735. static void deleteSubject() {
    736. MYSQL* mysql = &localMysql;
    737. sendInf("请输入要修改删除试题的考试名称: ");
    738. std::string subName = receiveInf();
    739. MysqlOperation::useQuery(mysql, "show tables");
    740. MYSQL_RES* result = mysql_store_result(mysql);
    741. MYSQL_ROW row;
    742. bool flags = false;
    743. while (row = mysql_fetch_row(result)) {
    744. if (row[0] == subName) {
    745. flags = true;
    746. break;
    747. }
    748. }
    749. mysql_free_result(result);
    750. if (!flags) {
    751. sendInf("false");
    752. }
    753. else {
    754. sendInf("true");
    755. }
    756. receiveInf();//保证程序正常运行
    757. if (!flags) {
    758. sendInf("没有该科目试卷");
    759. receiveInf();//保证程序正常运行
    760. }
    761. else {
    762. sendInf("当前试卷如下\n");
    763. receiveInf();//保证程序正常运行
    764. MysqlOperation::useQuery(mysql, "select * from `" + subName + "test`");
    765. result = mysql_store_result(mysql);
    766. int rnum = mysql_num_fields(result);
    767. std::string ans;
    768. while (row = mysql_fetch_row(result)) {
    769. for (int i = 0; i < rnum; i++) {
    770. if (i == 0) ans += "序号:";
    771. if (i == 1) {
    772. std::string ri = row[i];
    773. if (ri == "1") {
    774. ans += "类型:选择 代号:";
    775. }
    776. else if (ri == "2") {
    777. ans += "类型:填空 代号:";
    778. }
    779. else if (ri == "3") {
    780. ans += "类型:大题 代号:";
    781. }
    782. }
    783. else if (i == 2) ans += "题目:\n";
    784. else if (i == 3) ans += "分值:";
    785. else if (i == 4) ans += "答案:";
    786. ans += row[i];
    787. ans += "\n";
    788. }
    789. ans += "\n";
    790. }
    791. sendInf(ans);//送出试卷
    792. receiveInf();//保证程序正常运行
    793. sendInf("请选择要删除的题目编号");
    794. std::string number = receiveInf();//保证程序正常运行
    795. MysqlOperation::useQuery(mysql, "delete from `" + subName + "test` where id = '" + number + "'");
    796. }
    797. }
    798. //考试报名
    799. static void signUp(std::vector userInf) {
    800. MYSQL* mysql = &localMysql;
    801. std::string oper = "select `subName`, `time` from `subject` where `subName` is not null";
    802. bool res = MysqlOperation::useQuery(mysql, oper);
    803. if (res) sendInf("true");
    804. else sendInf("false");
    805. receiveInf();//保证程序正常运行
    806. if (res) {
    807. MYSQL_RES* result = mysql_store_result(mysql);
    808. MYSQL_ROW row;
    809. std::vector subjectList;
    810. std::vector timeList;
    811. while (row = mysql_fetch_row(result)) {
    812. subjectList.push_back(row[0]);
    813. timeList.push_back(row[1]);
    814. }
    815. mysql_free_result(result);
    816. sendInf("当前存在的考试科目及时间如下:\n");
    817. receiveInf();//保证程序正常运行
    818. int i = 0;
    819. std::string low;
    820. for (auto& j : subjectList) {
    821. ++i;
    822. low = low + std::to_string(i) + ": " + j + "\n"
    823. + "时间:\n" + timeList[i - 1] + "\n\n";
    824. }
    825. sendInf(low);
    826. receiveInf();//保证程序正常运行
    827. sendInf("请输入要报名的序号: ");
    828. std::string serial = receiveInf();//num 2 de -1
    829. int se = (int)strToLf(serial);
    830. bool lowss = se > subjectList.size() || se < 1;
    831. if (lowss) sendInf("true");
    832. else sendInf("false");
    833. receiveInf();//保证程序正常运行
    834. if (lowss) {
    835. sendInf("没有该考试信息!\n");
    836. receiveInf();//保证程序正常运行
    837. return;
    838. }
    839. else {
    840. oper = "select `studentAccont` from `" + subjectList[se - 1] + "` where studentAccont = '" + userInf[1] + "'";
    841. res = MysqlOperation::useQuery(mysql, oper);
    842. if (res) {
    843. MYSQL_RES* result = mysql_store_result(mysql);
    844. MYSQL_ROW row = mysql_fetch_row(result);
    845. if (row) sendInf("true");
    846. else sendInf("false");
    847. receiveInf();//保证程序正常运行
    848. if (row) {
    849. sendInf("当前考试您已报名\n");
    850. receiveInf();//保证程序正常运行
    851. return;
    852. }
    853. mysql_free_result(result);
    854. }
    855. oper = "select `id`, `name`, `major`, `grade`, `class`, `accont` from student where accont = '" + userInf[1] + "'";
    856. res = MysqlOperation::useQuery(mysql, oper);
    857. if (res) {
    858. MYSQL_RES* result = mysql_store_result(mysql);
    859. MYSQL_ROW row = mysql_fetch_row(result);
    860. int field = mysql_num_fields(result);
    861. std::vector oneStudent;
    862. std::string id = row[0];
    863. for (int i = 1; i < field; i++) {
    864. oneStudent.push_back(row[i]);
    865. }
    866. mysql_free_result(result);
    867. std::vector< std::vector> studentList;
    868. studentList.push_back(oneStudent);
    869. std::vector fieldList = { "studentName", "studentMajor","studentGrade","studentClass", "studentAccont" };
    870. if (MysqlOperation::addData(subjectList[se - 1], fieldList, studentList)) {
    871. std::vector fieldList2 = { "id", "accont","subjectName" };
    872. std::vector data = { id,userInf[1],subjectList[se - 1] };
    873. std::vector< std::vector> dataIn = { data };
    874. MysqlOperation::addData("entryForm", fieldList2, dataIn);
    875. MysqlOperation::addField("student", subjectList[se - 1] + "Score", "double", "", "", "");
    876. sendInf("报名成功\n");
    877. receiveInf();//保证程序正常运行
    878. }
    879. else {
    880. sendInf("报名失败\n");
    881. receiveInf();//保证程序正常运行
    882. }
    883. }
    884. }
    885. }
    886. }
    887. //开始考试
    888. static void beginTest(std::vector userInf) {
    889. MYSQL* mysql = &localMysql;
    890. std::string oper = "select subjectName from `entryForm` where accont = '" + userInf[1] + "'";
    891. bool res = MysqlOperation::useQuery(mysql, oper);
    892. if (res) {
    893. MYSQL_RES* result = mysql_store_result(mysql);
    894. MYSQL_ROW row = mysql_fetch_row(result);
    895. if (!row) sendInf("false");
    896. else sendInf("true");
    897. receiveInf();//保证程序正常运行
    898. if (!row) {
    899. sendInf("您当前未报名任何考试!\n");
    900. receiveInf();//保证程序正常运行
    901. }
    902. else {
    903. std::vectornameList;
    904. while (row) {
    905. nameList.push_back(row[0]);
    906. row = mysql_fetch_row(result);
    907. }
    908. mysql_free_result(result);
    909. sendInf("以下当前报名的考试\n");
    910. receiveInf();//保证程序正常运行
    911. std::string sendss;
    912. for (int i = 0; i < nameList.size(); i++) {
    913. sendss = sendss + std::to_string(i + 1) + ":" + nameList[i] + "\n";
    914. }
    915. sendInf(sendss);//送出已报名的考试列表
    916. receiveInf();//保证程序正常运行
    917. sendInf("请输入要参加考试的序号:\n");
    918. std::string se = receiveInf();//num 5 de -1
    919. sendInf(std::to_string(nameList.size()));//送出考试数量
    920. receiveInf();//保证程序正常运行
    921. if (strToLf(se) < 1 || strToLf(se) > nameList.size()) {
    922. sendInf("没有该选项\n");
    923. receiveInf();//保证程序正常运行
    924. }
    925. else {
    926. int sea = (int)strToLf(se);
    927. std::string oper = "show tables";
    928. res = MysqlOperation::useQuery(mysql, oper);
    929. result = mysql_store_result(mysql);
    930. bool have = false;
    931. while (row = mysql_fetch_row(result)) {
    932. if (row[0] == nameList[sea - 1] + "test") {
    933. have = true;
    934. break;
    935. }
    936. }
    937. mysql_free_result(result);
    938. if (!have) sendInf("false");
    939. else sendInf("true");
    940. receiveInf();//保证程序正常运行
    941. if (!have) {
    942. sendInf("当前考试老师还没有添加试卷\n");
    943. receiveInf();//保证程序正常运行
    944. }
    945. else {
    946. std::vector<double> scoreList(4);
    947. std::string oper = "select `id`, `type`, `topic`, `score`, `answer` from `" + nameList[sea - 1] + "test`";
    948. std::vector> testPaper;
    949. MysqlOperation::useQuery(mysql, oper);
    950. result = mysql_store_result(mysql);
    951. row = mysql_fetch_row(result);
    952. while (row) {
    953. std::vector subs;
    954. for (int i = 0; i < 5; i++) {
    955. subs.push_back(row[i]);
    956. }
    957. testPaper.push_back(subs);
    958. row = mysql_fetch_row(result);
    959. }
    960. mysql_free_result(result);
    961. std::vector<int> randomSubject = createRandList(1, testPaper.size());
    962. sendInf(std::to_string(randomSubject.size()));//送出试题数量
    963. receiveInf();//保证程序正常运行
    964. for (int i = 0; i < randomSubject.size(); i++) {
    965. std::string lows = "\n题目 " + std::to_string(i + 1) + ":\n" +
    966. testPaper[randomSubject[i] - 1][2] + "\n" +
    967. "该题分值: " + testPaper[randomSubject[i] - 1][3] + "\n";
    968. sendInf(lows);
    969. receiveInf();//保证程序正常运行
    970. std::string answers;
    971. sendInf(testPaper[randomSubject[i] - 1][1]);//送出试题类型
    972. receiveInf();//保证程序正常运行
    973. if (testPaper[randomSubject[i] - 1][1] == "1") {
    974. sendInf("请输入选项: ");
    975. answers = receiveInf();//string 15 de 未输入
    976. std::transform(answers.begin(), answers.end(), answers.begin(), ::toupper);
    977. if (testPaper[randomSubject[i] - 1][4] == answers) {
    978. scoreList[0] += strToLf(testPaper[randomSubject[i] - 1][3]);
    979. scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
    980. }
    981. }
    982. else if (testPaper[randomSubject[i] - 1][1] == "2") {
    983. sendInf("请输入答案,输入完成后另起一行输入~~~上传答案 ");
    984. answers = receiveInf();//string 500 ed 未输入
    985. if (testPaper[randomSubject[i] - 1][4] == answers) {
    986. scoreList[1] += strToLf(testPaper[randomSubject[i] - 1][3]);
    987. scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
    988. }
    989. }
    990. else {
    991. sendInf("请输入答案,输入完成后另起一行输入~~~上传答案 ");
    992. answers = receiveInf();//text 1024 未输入
    993. if (testPaper[randomSubject[i] - 1][4] == answers) {
    994. scoreList[2] += strToLf(testPaper[randomSubject[i] - 1][3]);
    995. scoreList[3] += strToLf(testPaper[randomSubject[i] - 1][3]);
    996. }
    997. }
    998. }
    999. sendInf("正在记录成绩...\n");
    1000. receiveInf();//保证程序正常运行
    1001. std::vector fieldList = { nameList[sea - 1] + "Score" };
    1002. std::vector sc = { lfToStr(scoreList[3]) };
    1003. MysqlOperation::modifyData("student", fieldList, sc, " accont = '" + userInf[1] + "'");
    1004. MysqlOperation::addData(nameList[sea - 1], std::vector{"studentName", "studentMajor", "studentGrade", "studentClass", "studentAccont", "score"}, std::vector>{std::vector{userInf[2], userInf[3], userInf[4], userInf[5], userInf[1], lfToStr(scoreList[0] + scoreList[1] + scoreList[2])}});
    1005. sendInf("记录完成!\n\n");
    1006. receiveInf();//保证程序正常运行
    1007. std::string lowss = "\n考试已完成, 题目已由系统批改,其中:\n选择题得分: "
    1008. + std::to_string(scoreList[0]) + "\n"
    1009. + "填空题得分: " + std::to_string(scoreList[1]) + "\n"
    1010. + "大题得分: " + std::to_string(scoreList[2]) + "\n\n"
    1011. + "总分: " + std::to_string(scoreList[3]) + "\n\n"
    1012. + "填空题,大题部分由于本系统的无能或许会出现误判,请\n等待老师手动重批,以上成绩仅供参考\n";
    1013. sendInf(lowss);
    1014. receiveInf();//保证程序正常运行
    1015. }
    1016. }
    1017. }
    1018. }
    1019. }
    1020. //查看成绩
    1021. static void checkResult(std::vector userInf) {
    1022. MYSQL* mysql = &localMysql;
    1023. MYSQL_RES* result;
    1024. MYSQL_ROW row;
    1025. std::string oper;
    1026. std::vector subjectName;
    1027. oper = "select subjectName from `entryForm` where accont = '" + userInf[1] + "'";
    1028. bool res = MysqlOperation::useQuery(mysql, oper);
    1029. if (res) {
    1030. result = mysql_store_result(mysql);
    1031. while (row = mysql_fetch_row(result)) {
    1032. subjectName.push_back(row[0]);
    1033. }
    1034. mysql_free_result(result);
    1035. }
    1036. oper = "select ";
    1037. for (int i = 0; i < subjectName.size(); i++) {
    1038. oper = oper + "`" + subjectName[i] + "Score`";
    1039. if (i < subjectName.size() - 1) {
    1040. oper += ",";
    1041. }
    1042. }
    1043. oper = oper + " from student where accont = '" + userInf[1] + "'";
    1044. res = MysqlOperation::useQuery(mysql, oper);
    1045. if (res) {
    1046. result = mysql_store_result(mysql);
    1047. MYSQL_FIELD* field;
    1048. std::string low;
    1049. while (field = mysql_fetch_field(result)) {
    1050. low += field->name;
    1051. low += "\t";
    1052. }
    1053. sendInf(low);
    1054. receiveInf();//保证程序正常运行
    1055. int column = mysql_num_fields(result);
    1056. std::string ans;
    1057. MYSQL_ROW row = mysql_fetch_row(result);
    1058. while (row) {
    1059. for (int i = 0; i < column; i++) {
    1060. if (row[i]) {
    1061. ans += row[i];
    1062. }
    1063. else {
    1064. ans += "null";
    1065. }
    1066. if (i < column - 1) {
    1067. ans += "\t";
    1068. if (i >= 7) {
    1069. ans += "\t";
    1070. }
    1071. }
    1072. }
    1073. ans += "\n";
    1074. row = mysql_fetch_row(result);
    1075. }
    1076. sendInf(ans);
    1077. receiveInf();//保证程序正常运行
    1078. mysql_free_result(result);
    1079. }
    1080. }
    1081. };
    1082. class User {
    1083. public:
    1084. //登录
    1085. static std::vector signIn() {
    1086. MYSQL* mysql;
    1087. MYSQL_RES* result;
    1088. MYSQL_ROW password;
    1089. std::vector re;
    1090. while (true) {
    1091. std::string sendOut = R"(
    1092. 登录:
    1093. 请选择身份:
    1094. 1 教师
    1095. 2 学生
    1096. 请输入序号:)";
    1097. sendInf(sendOut);//送出身份选择
    1098. std::string order = receiveInf();//获得身份
    1099. re.push_back(order);//储存身份
    1100. std::vector inf;
    1101. sendInf("server: 请输入账号:");
    1102. inf.push_back(receiveInf());//获得账号 string 20
    1103. sendInf("server: 请输入密码:");
    1104. inf.push_back(receiveInf());//获得密码 string 15
    1105. mysql = &localMysql;
    1106. std::string tors = "student";
    1107. if (order == "1") tors = "teacher";
    1108. std::string oper = "select `password` from `" + tors + "` where accont = '" + inf[0] + "'";
    1109. bool res = MysqlOperation::useQuery(mysql, oper);
    1110. result = mysql_store_result(mysql);
    1111. password = mysql_fetch_row(result);
    1112. std::string iferror = "false";
    1113. if (!password) {
    1114. iferror = "true";
    1115. }
    1116. sendInf(iferror);//发送错误情况
    1117. receiveInf();//保证正常运行
    1118. if (!password) {
    1119. mysql_free_result(result);
    1120. sendInf("server: 用户不存在,是否要创建账户? 1:创建 2:取消 请输入序号:");
    1121. std::string ins = receiveInf();//获得选择
    1122. if (ins == "1") {
    1123. userCreate();
    1124. }
    1125. continue;
    1126. }
    1127. else {
    1128. bool ifR = password[0] == inf[1];
    1129. if (ifR) sendInf("true");
    1130. else sendInf("false");
    1131. receiveInf();//保证正常运行
    1132. if (ifR) {
    1133. mysql_free_result(result);
    1134. bool low = MysqlOperation::useQuery(mysql, "select `accont`, `name`, `major`, `grade`, `class` from `student` where accont = '" + inf[0] + "'");
    1135. if (low) sendInf("true");//送出查询情况
    1136. else sendInf("false");//送出查询情况
    1137. receiveInf();//保证正常运行
    1138. if (low) {
    1139. result = mysql_store_result(mysql);
    1140. MYSQL_ROW row = mysql_fetch_row(result);
    1141. if (row) {
    1142. for (int i = 0; i < 5; i++) {
    1143. re.push_back(row[i]);
    1144. }
    1145. }
    1146. mysql_free_result(result);
    1147. sendInf("server: 登陆成功!");//送出选择
    1148. receiveInf();//保证正常运行
    1149. return re;
    1150. }
    1151. else {
    1152. sendInf("server: 登陆失败!");//送出选择
    1153. receiveInf();//保证正常运行
    1154. continue;
    1155. }
    1156. }
    1157. else {
    1158. sendInf("server: 账号或密码错误");
    1159. receiveInf();//保证正常运行
    1160. continue;
    1161. }
    1162. }
    1163. }
    1164. }
    1165. //创建用户
    1166. static void userCreate() {
    1167. sendInf(R"(
    1168. 请选择身份:
    1169. 1 教师
    1170. 2 学生
    1171. 请输入序号:)");
    1172. std::string order = receiveInf();//获得身份
    1173. std::vector inf;
    1174. sendInf("server: 请输入姓名:");
    1175. inf.push_back(receiveInf());//获得姓名,string 20
    1176. sendInf("server: 请输入专业:");
    1177. inf.push_back(receiveInf());//获得专业,string 20
    1178. if (order == "2") {
    1179. sendInf("server: 请输入年级:");
    1180. inf.push_back(receiveInf());//获得年级,int 2
    1181. sendInf("server: 请输入班级:");
    1182. inf.push_back(receiveInf());//获得班级 int 2
    1183. }
    1184. sendInf("server: 请输入电话:");
    1185. inf.push_back(receiveInf());//string 11
    1186. sendInf("server: 请输入账号:");
    1187. inf.push_back(receiveInf());//string 20
    1188. sendInf("server: 请输入密码:");
    1189. inf.push_back(receiveInf());//string 15
    1190. std::string tors = "student";
    1191. if (order == "1") tors = "teacher";
    1192. MYSQL* mysql = &localMysql;
    1193. std::string oper = "select * from `" + tors + "` where accont = " + inf[3];
    1194. bool res = MysqlOperation::useQuery(mysql, oper);
    1195. if (res) sendInf("true");//送出查询情况
    1196. else sendInf("false");//送出查询情况
    1197. receiveInf();//保证正常运行
    1198. if (res) {
    1199. MYSQL_RES* result = mysql_store_result(mysql);
    1200. MYSQL_ROW accont = mysql_fetch_row(result);
    1201. std::string ifExit = "false";
    1202. if (accont) {
    1203. ifExit = "true";
    1204. }
    1205. sendInf(ifExit);//送出账号是否存在的状态
    1206. receiveInf();//保证正常运行
    1207. if (accont) {
    1208. sendInf("server: 用户已存在!");
    1209. receiveInf();//保证正常运行
    1210. }
    1211. else {
    1212. std::vector field;
    1213. field.push_back("name");
    1214. field.push_back("major");
    1215. if (order == "2") {
    1216. field.push_back("grade");
    1217. field.push_back("class");
    1218. }
    1219. field.push_back("phone");
    1220. field.push_back("accont");
    1221. field.push_back("password");
    1222. std::vector> infIn;
    1223. infIn.push_back(inf);
    1224. bool res = MysqlOperation::addData(tors, field, infIn);
    1225. if (res) {
    1226. sendInf("server: 创建成功!");
    1227. receiveInf();//保证正常运行
    1228. }
    1229. else {
    1230. sendInf("server: 创建失败!");
    1231. receiveInf();//保证正常运行
    1232. }
    1233. }
    1234. mysql_free_result(result);
    1235. }
    1236. else {
    1237. std::cout << mysql_error(mysql) << std::endl;
    1238. }
    1239. }
    1240. //修改用户
    1241. static void modifyUser() {
    1242. MYSQL* mysql = &localMysql;
    1243. sendInf("请输入要修改的用户的身份:\n1:教师\n2:学生\n请输入:");
    1244. std::string orders = receiveInf();
    1245. if (orders == "1") {
    1246. orders = "teacher";
    1247. }
    1248. else {
    1249. orders = "student";
    1250. }
    1251. sendInf("请输入要修改的用户账号:\n");
    1252. std::string accont = receiveInf();
    1253. MysqlOperation::useQuery(mysql, "select * from `" + orders + "` where accont = '" + accont + "'");
    1254. MYSQL_RES* result = mysql_store_result(mysql);
    1255. MYSQL_ROW row = mysql_fetch_row(result);
    1256. if (row) sendInf("true");
    1257. else sendInf("false");
    1258. receiveInf();//保证程序正常运行
    1259. if (!row) {
    1260. sendInf("未找到该用户...\n");
    1261. receiveInf();//保证程序正常运行
    1262. }
    1263. else {
    1264. sendInf("已找到该用户:\n");
    1265. receiveInf();//保证程序正常运行
    1266. std::string fieldList;
    1267. std::string datas;
    1268. std::vector infList;
    1269. MYSQL_FIELD* field;
    1270. while (field = mysql_fetch_field(result)) {
    1271. fieldList += field->name;
    1272. fieldList += "\t";
    1273. }
    1274. fieldList += "\n";
    1275. int fnum = mysql_num_fields(result);
    1276. while (row) {
    1277. for (int i = 0; i < fnum; i++) {
    1278. infList.push_back(row[i]);
    1279. datas = datas + row[i] + "\t";
    1280. }
    1281. row = mysql_fetch_row(result);
    1282. }
    1283. mysql_free_result(result);
    1284. datas += "\n";
    1285. sendInf(fieldList + datas);//送出当前用户信息
    1286. receiveInf();//保证程序正常运行
    1287. sendInf("请开始修改以下信息,不修改的按回车跳过: \n");
    1288. receiveInf();//保证程序正常运行
    1289. std::vector dataList;
    1290. sendInf(infList[1]);//送出老姓名
    1291. receiveInf();//保证程序正常运行
    1292. sendInf("姓名:");
    1293. dataList.push_back(receiveInf());//获得新姓名
    1294. sendInf(infList[2]);//送出老专业
    1295. receiveInf();//保证程序正常运行
    1296. sendInf("专业:");
    1297. dataList.push_back(receiveInf());//获得新专业
    1298. if (orders == "student") {
    1299. sendInf(infList[3]);//送出老年级
    1300. receiveInf();//保证程序正常运行
    1301. sendInf("年级:");
    1302. dataList.push_back(receiveInf());//获得新年级
    1303. sendInf(infList[4]);//送出老班级
    1304. receiveInf();//保证程序正常运行
    1305. sendInf("班级:");
    1306. dataList.push_back(receiveInf());//获得新班级
    1307. sendInf(infList[5]);//送出老电话
    1308. receiveInf();//保证程序正常运行
    1309. sendInf("电话:");
    1310. dataList.push_back(receiveInf());//获得新电话
    1311. sendInf(infList[6]);//送出老账号
    1312. receiveInf();//保证程序正常运行
    1313. sendInf("账号:");
    1314. dataList.push_back(receiveInf());//获得新账号
    1315. sendInf(infList[7]);//送出老密码
    1316. receiveInf();//保证程序正常运行
    1317. sendInf("密码:");
    1318. dataList.push_back(receiveInf());//获得新密码
    1319. 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] + "' where `accont` = '" + accont + "'");
    1320. }
    1321. else {
    1322. sendInf(infList[3]);//送出老电话
    1323. receiveInf();//保证程序正常运行
    1324. sendInf("电话:");
    1325. dataList.push_back(receiveInf());//获得新电话
    1326. sendInf(infList[4]);//送出老账号
    1327. receiveInf();//保证程序正常运行
    1328. sendInf("账号:");
    1329. dataList.push_back(receiveInf());//获得新账号
    1330. sendInf(infList[5]);//送出老密码
    1331. receiveInf();//保证程序正常运行
    1332. sendInf("密码:");
    1333. dataList.push_back(receiveInf());//获得新密码
    1334. MysqlOperation::useQuery(mysql, "update `" + orders + "` set `name` = '" + dataList[0] + "', `major` = '" + dataList[1] + "', `phone` = '" + dataList[2] + "', `accont` = '" + dataList[3] + "', `password` = '" + dataList[4] + "' where `accont` = '" + accont + "'");
    1335. }
    1336. sendInf("修改完成");//送出信息
    1337. receiveInf();//保证程序正常运行
    1338. }
    1339. }
    1340. //删除用户
    1341. static void deleteUser() {
    1342. MYSQL* mysql = &localMysql;
    1343. sendInf("请输入要删除的用户的身份:\n1:教师\n2:学生\n请输入:");
    1344. std::string orders = receiveInf();
    1345. if (orders == "1") {
    1346. orders = "teacher";
    1347. }
    1348. else {
    1349. orders = "student";
    1350. }
    1351. sendInf("请输入要删除的用户账号:\n");
    1352. std::string accont = receiveInf();
    1353. MysqlOperation::useQuery(mysql, "select * from `" + orders + "` where accont = '" + accont + "'");
    1354. MYSQL_RES* result = mysql_store_result(mysql);
    1355. MYSQL_ROW row = mysql_fetch_row(result);
    1356. if (row) sendInf("true");
    1357. else sendInf("false");
    1358. receiveInf();//保证程序正常运行
    1359. if (!row) {
    1360. sendInf("未找到该用户...\n");
    1361. receiveInf();//保证程序正常运行
    1362. }
    1363. else {
    1364. sendInf("已找到该用户:\n");
    1365. receiveInf();//保证程序正常运行
    1366. std::string fieldList;
    1367. std::string datas;
    1368. std::vector infList;
    1369. MYSQL_FIELD* field;
    1370. while (field = mysql_fetch_field(result)) {
    1371. fieldList += field->name;
    1372. fieldList += "\t";
    1373. }
    1374. fieldList += "\n";
    1375. int fnum = mysql_num_fields(result);
    1376. while (row) {
    1377. for (int i = 0; i < fnum; i++) {
    1378. infList.push_back(row[i]);
    1379. datas = datas + row[i] + "\t";
    1380. }
    1381. row = mysql_fetch_row(result);
    1382. }
    1383. mysql_free_result(result);
    1384. datas += "\n";
    1385. sendInf(fieldList + datas);//送出当前用户信息
    1386. receiveInf();//保证程序正常运行
    1387. sendInf("是否删除? 1:是 2:否 请输入选择:");//送出当前用户信息
    1388. std::string ifd = receiveInf();
    1389. if (ifd == "1") {
    1390. MysqlOperation::useQuery(mysql, "delete from `" + orders + "` where accont = '" + accont + "'");
    1391. sendInf("删除完成\n");
    1392. receiveInf();//保证程序正常运行
    1393. }
    1394. else {
    1395. sendInf("取消删除\n");
    1396. receiveInf();//保证程序正常运行
    1397. }
    1398. }
    1399. }
    1400. };
    1401. bool flagss = true;
    1402. //界面与登录
    1403. class Visualization {
    1404. public:
    1405. //初始化
    1406. static void initialization() {
    1407. system("color E1");
    1408. std::cout << "正在初始化系统..." << std::endl;
    1409. std::string DBname = "ExaminationSystem";
    1410. MysqlOperation useSql;
    1411. useSql.ConnectDB("localhost", "root", "@Shang123", "mysql", 3306);
    1412. useSql.checkIfConnectDB();
    1413. std::cout << "正在创建基础表结构..." << std::endl;
    1414. useSql.createTable("teacher", "id", "int", "primary key", "auto_increment", "序号", "教师信息");
    1415. useSql.createTable("student", "id", "int", "primary key", "auto_increment", "序号", "学生信息");
    1416. useSql.createTable("subject", "id", "int", "primary key", "auto_increment", "序号", "考试科目");
    1417. useSql.createTable("entryForm", "id", "int", "", "", "学生序号", "考试科目");
    1418. useSql.addField("teacher", "name", "varchar(20)", "", "", "姓名");
    1419. useSql.addField("teacher", "major", "varchar(20)", "", "", "专业");
    1420. useSql.addField("teacher", "phone", "char(11)", "", "", "电话");
    1421. useSql.addField("teacher", "accont", "varchar(20)", "", "", "账号");
    1422. useSql.addField("teacher", "password", "varchar(15)", "", "", "密码");
    1423. useSql.addField("student", "name", "varchar(20)", "", "", "姓名");
    1424. useSql.addField("student", "major", "varchar(20)", "", "", "专业");
    1425. useSql.addField("student", "grade", "int", "", "", "年级");
    1426. useSql.addField("student", "class", "int", "", "", "班级");
    1427. useSql.addField("student", "phone", "char(11)", "", "", "电话");
    1428. useSql.addField("student", "accont", "varchar(20)", "", "", "账号");
    1429. useSql.addField("student", "password", "varchar(15)", "", "", "密码");
    1430. useSql.addField("subject", "subName", "varchar(50)", "", "", "科目名");
    1431. useSql.addField("subject", "fullScore", "int", "", "", "分值");
    1432. useSql.addField("subject", "time", "varchar(500)", "", "", "考试时间表");
    1433. useSql.addField("entryForm", "accont", "varchar(20)", "", "", "学生账号");
    1434. useSql.addField("entryForm", "subjectName", "varchar(50)", "", "", "报名科目");
    1435. std::cout << "创建成功..." << std::endl;
    1436. std::cout << "初始化完成!" << std::endl;
    1437. system("pause");
    1438. }
    1439. //开始界面
    1440. static void begin(std::string identity) {
    1441. if (identity == "2") {
    1442. sendInf(R"(
    1443. ?---------------0-0-0---------------?
    1444. | |
    1445. | 欢迎使用 好果zhi考试系统 |
    1446. | 本系统暂时没什么要给你说的... |
    1447. | 功能指令如下: |
    1448. | 1 登录 |
    1449. | 2 创建用户 |
    1450. | 3 考试报名 |
    1451. | 4 进行考试 |
    1452. | 5 查看成绩 |
    1453. | 6 离开系统 |
    1454. | author:阿白 |
    1455. | 2022/10/26 |
    1456. |___________________________________|
    1457. )");
    1458. receiveInf();//保证正常运行
    1459. }
    1460. else {
    1461. sendInf(R"(
    1462. ?---------------(>v<)---------------?
    1463. | |
    1464. | 欢迎使用 好果zhi考试系统 |
    1465. | 本系统暂时没什么要给你说的... |
    1466. | 功能指令如下: |
    1467. | 1 登录 |
    1468. | 2 创建用户 |
    1469. | 3 修改用户 |
    1470. | 4 删除用户 |
    1471. | 5 设置考试 |
    1472. | 6 创建试卷 |
    1473. | 7 添加试题 |
    1474. | 8 修改试题 |
    1475. | 9 删除试题 |
    1476. | 0 离开系统 |
    1477. | author:阿白 |
    1478. | 2022/10/26 |
    1479. |___________________________________|
    1480. )");
    1481. receiveInf();//保证正常运行
    1482. }
    1483. }
    1484. static std::string end() {//告别界面
    1485. sendInf(R"(
    1486. !---------------(=_=)---------------!
    1487. | |
    1488. | 就要告别了呢... |
    1489. | ... |
    1490. | 考试不快乐吗 |
    1491. | 还是本系统不好用呢 |
    1492. | |
    1493. | ########################### |
    1494. | ########################### |
    1495. | ...好吧 |
    1496. | 期待下次相见 |
    1497. | >_< |
    1498. |___________________________________|
    1499. )");
    1500. return receiveInf();//服务端是否要求主机关机
    1501. }
    1502. //登录界面
    1503. static std::vector signInVisual() {
    1504. std::vector userInf;
    1505. while (true) {
    1506. std::string face = R"(
    1507. ←---------------------- UnU ----------------------→
    1508. ` 注意: `
    1509. ` `
    1510. ` 在使用这个考试系统前,本系统要验证一下你的身份!`
    1511. ` 所以: `
    1512. ` `
    1513. ` 请先:1 登录 2 注册 `
    1514. 请输入序号:)";
    1515. sendInf(face);
    1516. std::string useMySystem = receiveInf();//获得选择
    1517. if (useMySystem == "1") {
    1518. userInf = User::signIn();
    1519. flagss = false;
    1520. }
    1521. else {
    1522. User::userCreate();
    1523. continue;
    1524. }
    1525. if (userInf.empty()) sendInf("true");
    1526. else sendInf("false");
    1527. receiveInf();//保证程序正常运行
    1528. if (userInf.empty()) {
    1529. continue;
    1530. }
    1531. break;
    1532. }
    1533. return userInf;
    1534. }
    1535. };
    1536. //子线程
    1537. DWORD WINAPI realize(LPVOID);
    1538. bool ts = false;
    1539. //socket初始化
    1540. bool socInitlz() {
    1541. WSADATA* wsaData = &localWsaData;
    1542. int res;
    1543. if (!WSAStartup(MAKEWORD(2, 2), wsaData)) {
    1544. std::cout << "绑定socket库成功" << std::endl;
    1545. }
    1546. else {
    1547. std::cout << "绑定socket库失败" << std::endl;
    1548. return false;
    1549. }
    1550. if (2 != LOBYTE(localWsaData.wVersion) || 2 != HIBYTE(localWsaData.wVersion)) {
    1551. WSACleanup();
    1552. std::cout << "WSADATA的版本不正确" << std::endl;
    1553. return false;
    1554. }
    1555. //创建套接字
    1556. serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    1557. //绑定套接字,配置监听地址和端口
    1558. SOCKADDR_IN svrAddr;
    1559. ZeroMemory((char*)&svrAddr, sizeof(svrAddr));
    1560. svrAddr.sin_family = AF_INET; //国际网区域
    1561. svrAddr.sin_port = htons(6000); //监听端口
    1562. svrAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //有IP
    1563. if (::bind(serverSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
    1564. std::cout << "配置监听失败: " << WSAGetLastError() << std::endl;
    1565. closesocket(serverSocket);
    1566. WSACleanup();
    1567. return false;
    1568. }
    1569. //监听
    1570. if (::listen(serverSocket, 10) == SOCKET_ERROR) {//最大连接数10个
    1571. std::cout << "system: 开启监听失败 " << WSAGetLastError() << std::endl;
    1572. closesocket(serverSocket);
    1573. WSACleanup();
    1574. return false;
    1575. }
    1576. std::cout << "system: 开启监听成功\n";
    1577. //接收套接字
    1578. SOCKADDR_IN clientAddr;
    1579. int length = sizeof(SOCKADDR);
    1580. //接收连接
    1581. if ((connectSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &length)) == INVALID_SOCKET) {
    1582. std::cout << "system: 接收消息失败" << WSAGetLastError() << std::endl;
    1583. closesocket(connectSocket);
    1584. WSACleanup();
    1585. return false;
    1586. }
    1587. HANDLE sendThread = CreateThread(nullptr, 0, realize, 0, 0, nullptr);
    1588. if (sendThread) {
    1589. CloseHandle(sendThread);
    1590. }
    1591. hMUTEX = CreateMutex(NULL, FALSE, L"mutex");
    1592. while (true) {
    1593. if (ts) {
    1594. std::cout << "客户端请求终止服务...";
    1595. break;
    1596. }
    1597. Sleep(100);
    1598. }
    1599. closesocket(serverSocket);
    1600. closesocket(connectSocket);
    1601. WSACleanup();
    1602. return true;
    1603. }
    1604. int main()
    1605. {
    1606. Visualization::initialization();
    1607. system("cls");
    1608. socInitlz();//初始化服务端并使用线程
    1609. return 0;
    1610. }
    1611. DWORD WINAPI realize(LPVOID) {
    1612. std::vector userInf;
    1613. if (flagss) {//只有第一次使用该程序时调用
    1614. userInf = Visualization::signInVisual();
    1615. }
    1616. sendInf(userInf[0]);//传递身份
    1617. receiveInf();//保证程序正常运行
    1618. while (true) {
    1619. Visualization::begin(userInf[0]);
    1620. sendInf("请输入您的指令: ");
    1621. std::string ins = receiveInf();//获得指令
    1622. if (ins == "1") {//登录
    1623. userInf = User::signIn();
    1624. }
    1625. else if(ins == "2") {//注册
    1626. User::userCreate();
    1627. }
    1628. else if (ins == "3") {
    1629. if (userInf[0] == "1") {
    1630. User::modifyUser();//修改用户
    1631. }
    1632. else {
    1633. Test::signUp(userInf);//考试报名
    1634. }
    1635. }
    1636. else if (ins == "4") {
    1637. if (userInf[0] == "1") {
    1638. User::deleteUser();//删除用户
    1639. }
    1640. else {
    1641. Test::beginTest(userInf);//开始考试
    1642. }
    1643. }
    1644. else if(ins == "5") {
    1645. if (userInf[0] == "1") {
    1646. //创建考试
    1647. Test::setTest();
    1648. }
    1649. else {
    1650. Test::checkResult(userInf);//查看成绩
    1651. }
    1652. }
    1653. else if (ins == "6") {
    1654. if (userInf[0] == "1") {
    1655. Test::createTest();//创建试卷
    1656. }
    1657. else {
    1658. Visualization::end();//告别系统
    1659. ts = true;
    1660. return 0;
    1661. }
    1662. }
    1663. else if (ins == "7") {
    1664. //添加试题
    1665. sendInf("请输入要添加题目的试卷名称:");
    1666. std::string subname = receiveInf();//string 50 未输入
    1667. Test::addSubject(subname + "test");
    1668. }
    1669. else if (ins == "8") {
    1670. Test::modifySubject();//修改试题
    1671. }
    1672. else if (ins == "9") {
    1673. Test::deleteSubject();//删除试题
    1674. }
    1675. else {
    1676. Visualization::end();
    1677. ts = true;
    1678. return 0;
    1679. }
    1680. }
    1681. }

    2.客户端的创建 

    头文件的添加同服务端

    代码:

    1. #include "stdafx.h"
    2. //便捷读取
    3. class SafeRead
    4. {
    5. public:
    6. //录入数字
    7. static std::string readNum(int length, const std::string& oldNum) {
    8. std::string inf;
    9. //label位置
    10. label:while (true) {
    11. std::cout << " 请输入数字:";
    12. getline(std::cin, inf);
    13. if (inf == "\n" || inf.empty()) {
    14. return oldNum;
    15. }
    16. else if ((int)inf.length() > length) {
    17. std::cout << "\n\t长度超过" << length << "位(计算需要包含小数点),请重新输入。\n";
    18. continue;
    19. }
    20. std::stringstream sin(inf);
    21. double d;
    22. char c;
    23. bool flag = true;
    24. if (!(sin >> d))
    25. flag = false;
    26. if (sin >> c)
    27. flag = false;
    28. if (!flag) {
    29. std::cout << "输入的不是一个数字,请重新输入" << std::endl;
    30. continue;
    31. }
    32. break;
    33. }
    34. //删除前导零
    35. std::string::iterator it = inf.begin();
    36. for (unsigned int i = 0; i < inf.length() - 1; i++) {//单0不删,一串0只留一个
    37. if (inf[i] == '-') continue;
    38. if (inf[i] != '0') break;
    39. if (inf[i] == '0' && inf[i + 1] == '.') break;
    40. inf.erase(it);
    41. it++;
    42. }
    43. return inf;
    44. }
    45. //录入有限制的字符串,用于读取基本信息
    46. static std::string readString(int length, std::string old) {
    47. std::string inf;
    48. while (true) {
    49. getline(std::cin, inf);
    50. if (inf == "\n" || inf.empty()) {
    51. return old;
    52. }
    53. else if ((int)inf.length() > length) {
    54. std::cout << "\n\t信息长度超过" << length << ",请重新输入。\n";
    55. continue;
    56. }
    57. return inf;
    58. }
    59. }
    60. //读取文本块,以~~~结束
    61. static std::string readText(int length, std::string old) {
    62. while (true) {
    63. std::string ans;
    64. while (true) {
    65. std::string inf;
    66. getline(std::cin, inf);
    67. if (inf == "~~~") {
    68. break;
    69. }
    70. else {
    71. ans = ans + inf + "\n";
    72. }
    73. }
    74. if (ans.size() > length) {
    75. std::cout << "当前文本长度(包括空格)为 " << ans.size() << ",已超过限定长度 " << length << ",请重新输入..." << std::endl;
    76. continue;
    77. }
    78. return ans;
    79. }
    80. }
    81. };
    82. double strToLf(const std::string& number) {
    83. double lf = 0, lfi = 0, x = 10;
    84. int i = 0, f = 1, times = 1, length = (int)number.length();
    85. while (number[i] < '0' || number[i] > '9') {//跳过可能存在的¥,$ 或 -
    86. i++;
    87. if (number[i] == '-')
    88. f *= -1;
    89. }
    90. //整数位
    91. while (i < length) {
    92. if (number[i] == '.') {
    93. break;
    94. }
    95. lf = lf * 10 + number[i] - '0';
    96. i++;
    97. }
    98. //小数位,++i跳过‘ . ’
    99. while (++i < length) {
    100. lfi += (number[i] - '0') / x;
    101. x *= 10;
    102. }
    103. return times * f * (lf + lfi);
    104. }
    105. WSADATA localWsaData;
    106. SOCKET clientSocket;
    107. HANDLE hMUTEX;
    108. DWORD WINAPI realize(LPVOID);
    109. using std::cout;
    110. using std::endl;
    111. int sendInf(std::string sendBuff);
    112. std::string receiveInf();
    113. void rev();
    114. void createUser();
    115. std::string signIn();
    116. void setTest();
    117. void createTest();
    118. void addSubject();
    119. void signUp();
    120. void beginTest();
    121. void checkResult();
    122. void modifySubject();
    123. void deleteSubject();
    124. void modifyUser();
    125. void deleteUser();
    126. //客户端线程
    127. DWORD WINAPI realize(LPVOID);
    128. bool ts = false;
    129. int main() {
    130. WSADATA* wsaData = &localWsaData;
    131. if (WSAStartup(MAKEWORD(1, 1), wsaData)) {
    132. std::cout << "加载WinSock错误" << std::endl;
    133. return false;
    134. }
    135. else {
    136. std::cout << "加载WinSock成功" << std::endl;
    137. }
    138. if (LOBYTE(localWsaData.wVersion) != 1 || HIBYTE(localWsaData.wVersion) != 1) {
    139. WSACleanup();
    140. return false;
    141. }
    142. //创建套接字
    143. clientSocket = socket(AF_INET, SOCK_STREAM, 0);
    144. if (clientSocket == INVALID_SOCKET) {
    145. std::cout << "套接字库创建失败" << std::endl;
    146. }
    147. else {
    148. std::cout << "套接字库创建成功" << std::endl;
    149. }
    150. //与服务端连接
    151. SOCKADDR_IN svrAddr;
    152. svrAddr.sin_family = AF_INET; //国际网区域
    153. svrAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//服务端IP
    154. svrAddr.sin_port = htons(6000); //监听端口
    155. if (connect(clientSocket, (SOCKADDR*)&svrAddr, sizeof(SOCKADDR)) == SOCKET_ERROR) {
    156. std::cout << "连接错误: " << WSAGetLastError() << std::endl;
    157. closesocket(clientSocket);
    158. WSACleanup();
    159. return false;
    160. }
    161. std::cout << "连接服务端成功" << std::endl;
    162. //创建子线程
    163. HANDLE sendThread = CreateThread(nullptr, 0, realize, 0, 0, nullptr);
    164. if (sendThread) {
    165. CloseHandle(sendThread);
    166. }
    167. hMUTEX = CreateMutex(NULL, FALSE, reinterpret_cast(L"mutex"));
    168. //给予线程使用
    169. while (true) {
    170. if (ts) {
    171. return 0;
    172. }
    173. Sleep(100);
    174. }
    175. closesocket(clientSocket);
    176. WSACleanup();
    177. return 0;
    178. }
    179. bool flag = false;
    180. DWORD WINAPI realize(LPVOID) {
    181. system("color E1");
    182. while (!flag) {
    183. system("cls");
    184. std::string order;
    185. rev();//获取开始登录界面
    186. std::string ins = SafeRead::readNum(1, "1");
    187. sendInf(ins);//送出选择
    188. if (ins == "1") {
    189. signIn();
    190. flag = true;
    191. }
    192. else {
    193. createUser();
    194. system("pause");
    195. continue;
    196. }
    197. std::string ifempty = receiveInf();
    198. sendInf("");//保证程序正常运行
    199. if (ifempty == "true") {
    200. continue;
    201. }
    202. system("pause");
    203. break;
    204. }
    205. std::string userInf = receiveInf();//获得身份
    206. sendInf("");//保证程序正常运行
    207. while (true) {
    208. system("cls");
    209. rev();//获得开始界面
    210. sendInf("");//保证程序正常运行
    211. rev();//请输入您的指令提醒
    212. std::string inf = SafeRead::readNum(1, "1");
    213. sendInf(inf);//送出指令
    214. if (inf == "1") {//登录
    215. userInf = signIn();
    216. }
    217. else if (inf == "2") {
    218. createUser();
    219. }
    220. else if (inf == "3") {
    221. if (userInf == "1") {
    222. modifyUser();
    223. }
    224. else {
    225. signUp();//考试报名
    226. }
    227. }
    228. else if (inf == "4") {
    229. if (userInf == "1") {
    230. deleteUser();
    231. }
    232. else {
    233. beginTest();//开始考试
    234. }
    235. }
    236. else if (inf == "5") {
    237. if (userInf == "1") {
    238. setTest();//设置考试
    239. }
    240. else {
    241. checkResult();//查看成绩
    242. }
    243. }
    244. else if (inf == "6") {
    245. if (userInf == "1") {
    246. createTest();//创建试卷
    247. }
    248. else {
    249. rev();//获得告别界面
    250. sendInf("1");//由于现在只连一个客户端,直接让服务端也关闭算了
    251. ts = true;
    252. system("pause");
    253. return 0;
    254. }
    255. }
    256. else if (inf == "7") {
    257. rev();//
    258. sendInf(SafeRead::readString(50, "未输入"));//输入试卷名
    259. addSubject();//添加试题
    260. }
    261. else if (inf == "8") {
    262. modifySubject();//修改试题
    263. }
    264. else if(inf == "9") {
    265. deleteSubject();//删除试题
    266. }
    267. else {
    268. rev();//获得告别界面
    269. sendInf("1");//由于现在只连一个客户端,直接让服务端也关闭算了
    270. ts = true;
    271. system("pause");
    272. return 0;
    273. }
    274. system("pause");
    275. }
    276. }
    277. int sendInf(std::string sendBuff) {
    278. sendBuff += '\0';
    279. if (sendBuff == "#") {
    280. sendBuff = "system: 用户端请求终止对话...\n";
    281. }
    282. int ret = send(clientSocket, sendBuff.c_str(), sizeof(char) * sendBuff.size(), 0);
    283. if (ret == SOCKET_ERROR) {
    284. std::cout << "system: 发送失败: " << WSAGetLastError() << std::endl;
    285. closesocket(clientSocket);
    286. WSACleanup();
    287. return -1;
    288. }
    289. else if (ret == 0) {
    290. std::cout << "system: 服务端断开连接: " << std::endl;
    291. closesocket(clientSocket);
    292. WSACleanup();
    293. return 0;
    294. }
    295. else {
    296. return 1;
    297. }
    298. }
    299. std::string receiveInf() {
    300. char recvBuff[3000]{};
    301. int flag = recv(clientSocket, recvBuff, 3000, 0);
    302. if (flag == SOCKET_ERROR) {
    303. std::cout << "system: 接收消息失败: " << WSAGetLastError();
    304. closesocket(clientSocket);
    305. WSACleanup();
    306. return "";
    307. }
    308. else if (!flag) {
    309. std::cout << "system: 服务端断开连接: " << WSAGetLastError();
    310. closesocket(clientSocket);
    311. WSACleanup();
    312. return "";
    313. }
    314. return recvBuff;
    315. }
    316. void rev() {//简化需要直接输出的接收数据
    317. cout << receiveInf() << endl;
    318. }
    319. //登录
    320. std::string signIn() {
    321. while (true) {
    322. std::string order;
    323. rev();//获取身份选择界面
    324. order = SafeRead::readNum(1, "1");//选择身份 1 教师 2 学生
    325. sendInf(order);
    326. rev();//接收身份报错
    327. sendInf(SafeRead::readString(20, "未输入"));//送出账号 最长20
    328. rev();//保证正常运行
    329. sendInf(SafeRead::readString(15, "未输入"));//送出密码 最长15
    330. std::string iferror = receiveInf();//接收错误情况
    331. sendInf("");//保证正常运行
    332. if (iferror == "true") {
    333. rev();//接收是否需要现在创建用户的选择 1 创建 2 不创建
    334. std::string ifc = SafeRead::readNum(1, "2");
    335. sendInf(ifc);//送出选择
    336. if (ifc == "1") {
    337. createUser();
    338. }
    339. continue;
    340. }
    341. else {
    342. std::string ifR = receiveInf();//接收密码是否正确的情况
    343. sendInf("");//保证正常运行
    344. if (ifR == "true") {
    345. std::string low = receiveInf();//接收查询情况
    346. sendInf("");//保证正常运行
    347. if (low == "true") {
    348. rev();//接收登陆成功提醒
    349. sendInf("");//保证正常运行
    350. return order;
    351. }
    352. else {
    353. rev();//接收登录失败提醒
    354. sendInf("");//保证正常运行
    355. continue;
    356. }
    357. }
    358. else {
    359. rev();//接收密码错误的提示
    360. sendInf("");//保证正常运行
    361. continue;
    362. }
    363. }
    364. }
    365. }
    366. void createUser() {
    367. rev();//获得身份选择界面
    368. std::string order = SafeRead::readNum(1, "1");//做出身份选择
    369. sendInf(order);
    370. rev();//提示输入姓名
    371. sendInf(SafeRead::readString(20, "未输入"));//送出姓名
    372. rev();
    373. sendInf(SafeRead::readString(20, "未输入"));//送出专业
    374. if (order == "2") {
    375. rev();
    376. sendInf(SafeRead::readNum(2, "-1"));//送出年级
    377. rev();
    378. sendInf(SafeRead::readNum(2, "-1"));//送出班级
    379. }
    380. rev();
    381. sendInf(SafeRead::readString(11, "未输入"));//送出电话
    382. rev();
    383. sendInf(SafeRead::readString(20, "未输入"));//送出账号
    384. rev();
    385. sendInf(SafeRead::readString(15, "未输入"));//送出密码
    386. std::string ins = receiveInf();//接收搜索状态
    387. sendInf("");//保证正常运行
    388. if (ins == "true") {
    389. std::string low = receiveInf();
    390. sendInf("");//保证正常运行
    391. if (low == "true") {//判断账号是否存在的搜索//保证正常运行
    392. rev();//接收账号已存在的反馈
    393. sendInf("");//保证正常运行
    394. }
    395. else {
    396. rev();//打印创建反馈
    397. sendInf("");//保证正常运行
    398. }
    399. }
    400. else {
    401. cout << "\n创建出现错误" << endl;
    402. }
    403. }
    404. void setTest() {
    405. rev();
    406. sendInf(SafeRead::readString(50, "未输入"));//传递考试科目
    407. rev();
    408. sendInf(SafeRead::readNum(5, "-1"));//传递考试分值
    409. rev();
    410. sendInf(SafeRead::readText(500, "未输入"));//传递考试时间表
    411. std::string low = receiveInf();//接收res
    412. sendInf("");//保证程序正常运行
    413. if (low == "true") {
    414. rev();//接收设置成功的消息
    415. sendInf("");//保证程序正常运行
    416. }
    417. }
    418. void createTest() {
    419. rev();
    420. sendInf(SafeRead::readString(50, "未输入"));//传递考试科目
    421. std::string low = receiveInf();//接收res
    422. sendInf("");//保证程序正常运行
    423. if (low == "true") {
    424. std::string res = receiveInf();//接收该科目考试是否为空的消息
    425. sendInf("");//保证程序正常运行
    426. if (res == "true") {
    427. rev();//接收现在是否设置考试的消息 1 设置 2 不设置
    428. std::string lows = SafeRead::readNum(1, "2");
    429. sendInf(lows);//传递选择
    430. if (lows == "1") {
    431. setTest();
    432. }
    433. else {
    434. return;
    435. }
    436. }
    437. else {
    438. addSubject();
    439. }
    440. }
    441. }
    442. void addSubject() {
    443. rev();//接收请开始添加试题的提示
    444. sendInf("");//保证程序正常运行
    445. while (true) {
    446. std::string type;
    447. rev();//选择题目类型
    448. type = SafeRead::readNum(1, "1");
    449. sendInf(type);//传入题目类型
    450. if (type == "4") {
    451. break;
    452. }
    453. if (type != "1" && type != "2" && type != "3") {
    454. rev();//无该类型的提醒
    455. sendInf("");//保证程序正常运行
    456. }
    457. rev();
    458. sendInf(SafeRead::readText(1024, "未输入"));//传入题目类型
    459. while (true) {
    460. rev();//请输入分值的提醒
    461. std::string inf = SafeRead::readNum(4, "-1");
    462. sendInf(inf);//传递分值
    463. if (inf.c_str()[0] == '-' || inf == "0") {
    464. rev();//分值大于0提醒
    465. sendInf("");
    466. continue;
    467. }
    468. break;
    469. }
    470. if (type == "1") {
    471. rev();//请输入答案选项提醒
    472. sendInf(SafeRead::readString(10, "0"));//获得答案
    473. }
    474. else {
    475. rev();
    476. sendInf(SafeRead::readText(1024, "未输入"));//获得答案
    477. }
    478. rev();//接收回车
    479. sendInf("");//保证程序正常运行
    480. }
    481. }
    482. void signUp() {
    483. std::string res = receiveInf();//读取res
    484. sendInf("");//保证程序正常运行
    485. if (res == "true") {
    486. rev();//接收考试科目提示
    487. sendInf("");//保证程序正常运行
    488. rev();//接收考试科目及时间
    489. sendInf("");//保证程序正常运行
    490. rev();//报名序号提醒
    491. sendInf(SafeRead::readNum(2, "-1"));
    492. std::string low = receiveInf();//接收序号是否正确信息
    493. sendInf("");//保证程序正常运行
    494. if (low == "true") {
    495. rev();//没有考试提醒
    496. sendInf("");//保证程序正常运行
    497. }
    498. else {
    499. low = receiveInf();//接收row
    500. sendInf("");//保证程序正常运行
    501. if (low == "true") {
    502. rev();//接收考试已报名提醒
    503. sendInf("");//保证程序正常运行
    504. return;
    505. }
    506. rev();//接收是否报名成功提醒
    507. sendInf("");//保证程序正常运行
    508. }
    509. }
    510. }
    511. void beginTest() {
    512. std::string row = receiveInf();//接收row
    513. sendInf("");//保证程序正常运行
    514. if (row == "false") {
    515. rev();//接收未报名考试的提醒
    516. sendInf("");//保证程序正常运行
    517. }
    518. else {
    519. rev();//当前报名考试列表的提醒
    520. sendInf("");//保证程序正常运行
    521. rev();//接收已报名的考试列表
    522. sendInf("");//保证程序正常运行
    523. rev();//获取考试序号提醒
    524. std::string ins = SafeRead::readNum(5, "-1");
    525. sendInf(ins);
    526. std::string num = receiveInf();//接收考试数量
    527. sendInf("");//保证程序正常运行
    528. if (strToLf(ins) < 1 || strToLf(ins) > strToLf(num)) {
    529. rev();//没有该选项提醒
    530. sendInf("");//保证程序正常运行
    531. }
    532. else {
    533. std::string have = receiveInf();//接收试卷情况
    534. sendInf("");//保证程序正常运行
    535. if (have == "false") {
    536. rev();
    537. sendInf("");//保证程序正常运行
    538. }
    539. else {
    540. std::string number = receiveInf();//接收试题数量
    541. sendInf("");//保证程序正常运行
    542. for (int i = 0; i < strToLf(number); i++) {
    543. rev();//收到一个试题
    544. sendInf("");//保证程序正常运行
    545. std::string type = receiveInf();//接收试题类型
    546. sendInf("");//保证程序正常运行
    547. if (type == "1") {
    548. rev();//请输入选项提醒
    549. sendInf(SafeRead::readString(15, "未输入"));
    550. }
    551. else if (type == "2") {
    552. rev();
    553. sendInf(SafeRead::readText(500, "未输入"));
    554. }
    555. else {
    556. rev();
    557. sendInf(SafeRead::readText(1024, "未输入"));
    558. }
    559. }
    560. rev();//正在记录成绩提醒
    561. sendInf("");//保证程序正常运行
    562. rev();//考试成绩判断
    563. sendInf("");//保证程序正常运行
    564. rev();//获得考试判断
    565. sendInf("");//保证程序正常运行
    566. }
    567. }
    568. }
    569. }
    570. //查看成绩
    571. void checkResult() {
    572. rev();//接收参加的考试列表
    573. sendInf("");//保证程序正常运行
    574. rev();//接收成绩
    575. sendInf("");//保证程序正常运行
    576. }
    577. //修改题目
    578. void modifySubject() {
    579. rev();
    580. sendInf(SafeRead::readString(50,"未输入"));//请输入要修改试题的考试名称
    581. std::string flags = receiveInf();//接收flags
    582. sendInf("");//保证程序正常运行
    583. if (flags == "false") {
    584. rev();
    585. sendInf("");//保证程序正常运行
    586. }
    587. else {
    588. rev();//当前试卷如下提醒
    589. sendInf("");//保证程序正常运行
    590. rev();//接收试卷
    591. sendInf("");//保证程序正常运行
    592. rev();
    593. sendInf(SafeRead::readNum(1, "1"));//请输入要修改的题目编号
    594. rev();//请重新输入题目
    595. sendInf("");//保证程序正常运行
    596. while (true) {
    597. rev();
    598. std::string type = SafeRead::readNum(1, "1");
    599. sendInf(type);//请输入题目类型
    600. if (type != "1" && type != "2" && type != "3") {
    601. rev();
    602. sendInf("");//保证程序正常运行
    603. continue;
    604. }
    605. rev();
    606. sendInf(SafeRead::readText(1024, "未输入"));
    607. while (true) {
    608. rev();
    609. std::string scores = SafeRead::readNum(4, "-1");
    610. sendInf(scores);
    611. if (scores.c_str()[0] == '-' || scores == "0") {
    612. rev();
    613. sendInf("");//保证程序正常运行
    614. continue;
    615. }
    616. break;
    617. }
    618. if (type == "1") {
    619. rev();
    620. sendInf(SafeRead::readString(1, "0"));
    621. }
    622. else {
    623. rev();
    624. sendInf(SafeRead::readText(1024, "未输入"));
    625. }
    626. rev();
    627. sendInf("");//保证程序正常运行
    628. break;
    629. }
    630. rev();//修改成功报告
    631. sendInf("");//保证程序正常运行
    632. }
    633. }
    634. //删除题目
    635. void deleteSubject() {
    636. rev();
    637. sendInf(SafeRead::readString(50, "未输入"));//请输入要删除试题的考试名称
    638. std::string flags = receiveInf();//接收flags
    639. sendInf("");//保证程序正常运行
    640. if (flags == "false") {
    641. rev();
    642. sendInf("");//保证程序正常运行
    643. }
    644. else {
    645. rev();//当前试卷如下提醒
    646. sendInf("");//保证程序正常运行
    647. rev();//接收试卷
    648. sendInf("");//保证程序正常运行
    649. rev();
    650. sendInf(SafeRead::readNum(1, "1"));//请输入要删除的题目编号
    651. std::cout << "删除成功\n\n";
    652. }
    653. }
    654. //修改用户
    655. void modifyUser() {
    656. rev();
    657. std::string order = SafeRead::readNum(1, "1");
    658. sendInf(order);//送出身份选择
    659. if (order == "1") {
    660. order = "teacher";
    661. }
    662. else {
    663. order = "student";
    664. }
    665. rev();
    666. sendInf(SafeRead::readString(15, "未输入"));//送出要修改的账号
    667. std::string row = receiveInf();//接收row
    668. sendInf("");//保证程序正常运行
    669. if (row == "false") {
    670. rev();
    671. sendInf("");//保证程序正常运行
    672. }
    673. else {
    674. rev();
    675. sendInf("");//保证程序正常运行
    676. rev();//接收当前用户信息
    677. sendInf("");//保证程序正常运行
    678. rev();//接收当前开始修改提示信息
    679. sendInf("");//保证程序正常运行
    680. std::string oldInf;
    681. oldInf = receiveInf();//接收老姓名
    682. sendInf("");//保证程序正常运行
    683. rev();//接收提示信息
    684. sendInf(SafeRead::readString(20, oldInf));//送出新姓名
    685. oldInf = receiveInf();//接收老专业
    686. sendInf("");//保证程序正常运行
    687. rev();//接收提示信息
    688. sendInf(SafeRead::readString(20, oldInf));//送出新专业
    689. if (order == "student") {
    690. oldInf = receiveInf();//接收老年级
    691. sendInf("");//保证程序正常运行
    692. rev();//接收提示信息
    693. sendInf(SafeRead::readNum(1, oldInf));//送出新年级
    694. oldInf = receiveInf();//接收老班级
    695. sendInf("");//保证程序正常运行
    696. rev();//接收提示信息
    697. sendInf(SafeRead::readNum(1, oldInf));//送出新班级
    698. }
    699. oldInf = receiveInf();//接收老电话
    700. sendInf("");//保证程序正常运行
    701. rev();//接收提示信息
    702. sendInf(SafeRead::readString(11, oldInf));//送出新电话
    703. oldInf = receiveInf();//接收老账号
    704. sendInf("");//保证程序正常运行
    705. rev();//接收提示信息
    706. sendInf(SafeRead::readString(20, oldInf));//送出新账号
    707. oldInf = receiveInf();//接收老密码
    708. sendInf("");//保证程序正常运行
    709. rev();//接收提示信息
    710. sendInf(SafeRead::readString(15, oldInf));//送出新密码
    711. rev();
    712. sendInf("");//保证程序正常运行
    713. }
    714. }
    715. //删除用户
    716. void deleteUser() {
    717. rev();
    718. std::string order = SafeRead::readNum(1, "1");
    719. sendInf(order);//送出身份选择
    720. if (order == "1") {
    721. order = "teacher";
    722. }
    723. else {
    724. order = "student";
    725. }
    726. rev();
    727. sendInf(SafeRead::readString(15, "未输入"));//送出要删除的账号
    728. std::string row = receiveInf();//接收row
    729. sendInf("");//保证程序正常运行
    730. if (row == "false") {
    731. rev();
    732. sendInf("");//保证程序正常运行
    733. }
    734. else {
    735. rev();
    736. sendInf("");//保证程序正常运行
    737. rev();//接收当前用户信息
    738. sendInf("");//保证程序正常运行
    739. rev();//接收是否删除的选择
    740. std::string inf = SafeRead::readNum(1, "2");
    741. sendInf(inf);//送出选择
    742. rev();//接收报告消息
    743. sendInf("");//保证程序正常运行
    744. }
    745. }

    五、小结 

    这次实训可谓打了我个措手不及,实训开始前两天才说要用mysql和socket。我只得紧赶慢赶肝了两天学完了mysql基础的语法,而socket则是完全没时间学,,后面完成通信时也是吃了非常大的亏,以至于压到最后时刻才勉强完成,还有很多预期的功能没有做,最后几个做完的功能也有些暴力开发的意思,没有考虑代码精简的问题,容错也不到位。

    最后还是那句:如果有bug,请一定一定告诉我!感谢!!!

  • 相关阅读:
    什么是区块链粉尘攻击?
    VSCode设置快捷键
    java毕业设计教务管理系统(附源码、数据库)
    ceph 线程池分析
    Freezable ---探索WPF中Freezable承载数据的原理
    基于 YOLOV5 的 SAR 图像舰船检测
    shell之常用小工具(sort、uniq、tr、cut)
    微服务架构终极指南
    13.RPC的socket实现(阻塞式)与netty实现(非阻塞式)
    IGP高级特性简要介绍(OSPF-上篇)
  • 原文地址:https://blog.csdn.net/bairimeng16/article/details/127671113