main.cpp
首先给出main的源码,随后再来进行相关解释。
//main.cpp
int main()
{
Interface main;
main.Hello();
while (true)
{
try{
Interpret(main.Input());
} catch (std::exception& e){
using namespace std;
cout << "#ERROR " << e.what() << endl<< endl;
#ifdef _TEST5_
clog << std::cin.eof() << " " << std::cin.bad() << " " << std::cin.fail() << std::endl;
#endif
// cin.ignore(numeric_limits<std::streamsize>::max());
fflush(stdin); cin.clear();
system("color 1F"); time_cnt::Sleep2(); system("color 0F");
} catch(...){
std::cout << "#WARNING: UNKNOWN EXCEPTION OCCURED" << std::endl;
}
if (main.exit())
break;
}
main.Goodbye();
}
程序结构
对于main函数我们采取了类似FLTK lab的技术,类似先申请窗口,再对窗口进行操作,这里我们申请一个交互体的对象。结构如下
class Interface
{
public:
void Hello();
std::string Input();
void Goodbye();
bool exit() const { return exit_; }
private:
bool exit_;
};
Hello、Goodbye函数,主要功能是表示MySQL的进入和退出两个交互方式
exit函数是退出的bool状态的对外接口。
它们的实现:
其中三个函数Intro,Blingbling,FakeUser的函数说明已经简要写在代码里:
void Interface::Hello()
{
Intro();//basic info output interface
Blingbling();//dynamic start flash animation
using std::cin;
using std::cout;
using std::endl;
cout << "Windows PowerShell" << endl
<< "版权所有 (C) Microsoft Corporation。保留所有权利。" << endl
<< "尝试新的跨平台 PowerShell https://aka.ms/pscore6" << endl
<< "PS C:\\Users\\abc44> ";
FakeUser("net start mysql");// simulation of user inputting.
cout << "请求的服务已经启动。\n\n"
<< "请键入 NET HELPMSG 2182 以获得更多的帮助。\n\n";
cout << "PS C:\\Users\\abc44> ";
FakeUser("cd D:\\Mysql\\mysql-8.0.19-winx64\\bin");
cout << "PS D:\\Mysql\\mysql-8.0.19-winx64\\bin> ";
FakeUser("mysql -u root -p");
cout << "Enter password: ";
FakeUser("********");
cout << "Welcome to the MySQL monitor. Commands end with ; or \\g.\n";
cout << "Your MySQL connection id is 9\n";
cout << "Server version: 8.0.19 MySQL Community Server - GPL\n\n";
cout << "Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.\n\n";
cout << "Oracle is a registered trademark of Oracle Corporation and/or its\n";
cout << "affiliates. Other names may be trademarks of their respective\n";
cout << "owners.\n\n";
cout << "Type 'help;' or '\\h' for help. Type '\\c' to clear the current input statement.\n\n";
}
其中Input函数为循环输入,并进行异常保护,保证其输入缓冲区不空。同时保证多行输入被有效识别,我们还添加了stringstream
实现:如果此行有有效输入。
std::string Interface::Input()
{
using namespace std;
cout << kMysql;
string line, sentence;
stringstream ss;
bool already_in = false, danger = true;// to indicate whether we have input or not
while (getline(cin, line))
{
danger = false;
if (already_in && line.size() > 1)
ss << ' ';
if (line.size()){
ss << line;
already_in = true;
}
if (line[line.size()-1] == ';'){
sentence = ss.str(); // using `ss>>` we'll only get the first word of ss.
//(which is defined by the rules of stream inserting)
break;
}
else
cout << " -> ";
}
extern bool broken;
if (danger)
if (broken)
error("Data Broken");
else
error("No input at all");
time_cnt::start();
#ifdef _LOC_
cout << "src sentence was : " << sentence << endl;
#endif
if (sentence == "exit;")
exit_ = true;
return sentence;
}
期中的错误处理我们采用了一点和MySQL不太相同的地方,就是利用时间操作进行短暂的蓝屏警告。
debug要点
- 在正式开始后续的编写之前,我们应该做好异常的架设。这样对我们寻找bug很有帮助。同时良好的log机制也有这样的作用。
- log应该准确地说明程序的动作,用高辨识度的语言,表明它在哪里干了什么事。利用编译宏选项实在很有帮助。
- 不要急于封装,比如文中的几个添加的几个接口。如果先写好函数构架,很容易中途易辙,左支右绌。先使用比较熟悉的程序设计语言写好,再寻找有没有哪里可以优化,对于并不熟悉函数式编程的我来说是一个比较好的选择。
stringstream
是个好东西。