[C++] 纯文本查看 复制代码
#include <iostream>
#include <mysql/mysql.h>
#include <mutex>
#include <string>
#include <vector>
#include <iomanip>
namespace wind
{
#define COMMAND_BUF_SIZE 256
// 状态
enum Flags
{
SHOW, // 只显示数据
FIRST, // 第一次全部读取数据
SECOND // 第二次直接读取表单最后一行插入数组 提高效率
};
// 数据
struct Data
{
std::string strEnglish;
std::string strChinese;
};
// 数据库
class Mysql
{
private:
MYSQL m_mysql;
std::mutex m_mutex;
std::string m_strRoot;
std::string m_strUser;
std::string m_strPassword;
std::string m_strDatabase;
std::string m_strTableName;
int m_nPost;
char m_commandBuf[COMMAND_BUF_SIZE]{};
std::vector<std::string> m_chineseWords;
public:
// +--------------------+
// | id english chinese |
// | 1 苹果 apple |
// | 2 香蕉 banana |
// +--------------------+
// 获取中文
inline std::vector<std::string> getChineseWords() const
{
return this->m_chineseWords;
}
// 初始化数据库
bool init(const std::string &strRoot, const std::string &strUser, const std::string &strPassword, const std::string &strDatabase, const std::string &strTableName, int nPort)
{
// 隐式构造(形参) + 移动构造(提升效率)
this->m_strRoot = std::move(strRoot);
this->m_strUser = std::move(strUser);
this->m_strPassword = std::move(strPassword);
this->m_strDatabase = std::move(strDatabase);
this->m_strTableName = std::move(strTableName);
this->m_nPost = nPort;
if ((mysql_init(&this->m_mysql)) == nullptr)
{
printf("%s.%d error!\n", __func__, __LINE__);
return false;
}
std::lock_guard<std::mutex> lockguard(this->m_mutex);
if ((mysql_library_init(0, nullptr, nullptr)) != 0)
{
printf("%s.%d error!\n", __func__, __LINE__);
return false;
}
return true;
}
// 连接数据库
bool connect()
{
// 连接数据库
if ((mysql_real_connect(&this->m_mysql, this->m_strRoot.data(), this->m_strUser.data(),
this->m_strPassword.data(), this->m_strDatabase.data(), m_nPost, nullptr, 0)) == nullptr)
return false;
// 设置字符集
if (mysql_query(&this->m_mysql, "set names utf8"))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return false;
}
sprintf(this->m_commandBuf, "use %s", this->m_strDatabase.data());
// 使用哪一个数据库
if (mysql_query(&this->m_mysql, this->m_commandBuf))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return false;
};
return true;
}
// 插入数据库
bool insert(const Data &data)
{
if (this->m_strTableName.empty() || data.strEnglish.empty() || data.strChinese.empty())
return false;
sprintf(this->m_commandBuf, "insert into %s(english, chinese) values('%s', '%s')",
this->m_strTableName.data(), data.strEnglish.data(), data.strChinese.data());
if (mysql_query(&this->m_mysql, m_commandBuf))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return false;
}
return true;
}
// 查询数据
bool querys(Flags flags)
{
MYSQL_RES *results;
MYSQL_FIELD *fields;
MYSQL_ROW rows;
unsigned int nNumfields;
if (flags != SECOND)
{
sprintf(this->m_commandBuf, "select *from %s", this->m_strTableName.data());
if (mysql_query(&this->m_mysql, this->m_commandBuf))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return false;
}
// 获取结果集
if ((results = (mysql_store_result(&this->m_mysql))) == nullptr)
{
printf("%s.%d error!\n", __func__, __LINE__);
return false;
}
// 获取一共有多少列
nNumfields = mysql_num_fields(results);
// 只显示数据
if (flags == SHOW)
{
// 获取字段名
while (fields = (mysql_fetch_field(results)))
std::cout << std::setw(15) << fields->name;
std::cout << std::endl;
// 循环获取数据
while (rows = (mysql_fetch_row(results)))
{
for (int i = 0; i < nNumfields; ++i)
{
if (rows[i])
std::cout << std::setw(15) << rows[i];
}
std::cout << std::endl;
}
}
// 全部数据存入数组
else if (flags == FIRST)
{
while (rows = (mysql_fetch_row(results)))
{
for (int i = 0; i < nNumfields; ++i)
this->m_chineseWords.push_back(rows[2]);
}
}
return true;
}
// 读取最后一行数据 直接放入数组
if (flags == SECOND)
{
sprintf(this->m_commandBuf, "select *from %s where id=(select max(id) from %s)", this->m_strTableName.data(), this->m_strTableName.data());
if (mysql_query(&this->m_mysql, this->m_commandBuf))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return false;
}
// 获取结果集
if ((results = (mysql_store_result(&this->m_mysql))) == nullptr)
{
printf("%s.%d error!\n", __func__, __LINE__);
return false;
}
// 因为只有一行数据 所以获取一次即可
if ((rows = mysql_fetch_row(results)) == nullptr)
return false;
// 放入数组
this->m_chineseWords.push_back(rows[2]);
}
mysql_free_result(results);
return true;
}
// 查询单行数据
std::vector<std::string> query(const std::string &data, const std::string &from)
{
if (data.empty())
return {};
MYSQL_RES *results;
MYSQL_ROW rows;
sprintf(this->m_commandBuf, "select *from %s where chinese = '%s'", this->m_strTableName.data(), data.data());
if (mysql_query(&this->m_mysql, this->m_commandBuf))
{
printf("%s.%d %s\n", __func__, __LINE__, mysql_error(&this->m_mysql));
return {};
}
if ((results = (mysql_store_result(&this->m_mysql))) == nullptr)
return {};
rows = mysql_fetch_row(results);
if (from == "h")
return {rows[1]};
else if (rows[1] == from)
printf("\033[32mnice!\n\033[0m");
else
printf("\033[31merror!\n\033[0m");
return {};
}
public:
// 单例模式
static Mysql &getInstance()
{
static Mysql mysql;
return mysql;
}
private:
Mysql() = default;
Mysql(const Mysql &) = delete;
const Mysql &operator =(const Mysql &) = delete;
~Mysql()
{
std::lock_guard<std::mutex> lockGuard(this->m_mutex);
mysql_library_end();
mysql_close(&this->m_mysql);
}
};
};
int main(void)
{
srand((unsigned int)(time(nullptr)));
printf("\033[31mtype(h = help, i = insert)\n\033[0m");
wind::Mysql::getInstance().init("localhost", "root", "123456", "words","first", 3306);
wind::Mysql::getInstance().connect();
// wind::Mysql::getInstance().insert({"apple", "苹果"});
// wind::Mysql::getInstance().insert({"orange", "橘子"});
// wind::Mysql::getInstance().insert({"peach", "桃子"});
// wind::Mysql::getInstance().insert({"pear", "梨子"});
// wind::Mysql::getInstance().insert({"watermelon", "西瓜"});
wind::Mysql::getInstance().querys(wind::FIRST);
std::vector<std::string> key;
std::string value;
int nLen;
auto init = [&key, &nLen]()
{
// 获取数组 此时数组里面已经存好了中文
key = wind::Mysql::getInstance().getChineseWords();
nLen = key.size();
};
init();
while (1)
{
value.clear();
int i = rand() % nLen;
// 随机从数组里面选择一个中文单词
printf("Please type the corresponding English %s: ", key[i].data());
std::cin >> value;
// 显示答案
if (value == "h")
{
auto answer = wind::Mysql::getInstance().query(key[i].data(), value);
printf("%s\n", answer[0].data());
}
// 插入数据
if (value == "i")
{
std::string chi;
std::string eng;
printf("english:");
std::cin >> eng;
printf("chinese:");
std::cin >> chi;
wind::Mysql::getInstance().insert({eng, chi});
wind::Mysql::getInstance().querys(wind::SHOW);
init();
wind::Mysql::getInstance().querys(wind::SECOND);
continue;
}
// 查询输入的数据 是否正确
wind::Mysql::getInstance().query(key[i].data(), value);
}
return 0;
}