【项目源码分享】基于C++实现的小型数据库(Windows/Linux环境)
目錄
前言
項目介紹
功能實現
重要說明
源代碼分享
寫在最后
前言
程設實驗終于收工了!🎉
終于到了本學期最后一個項目,可謂是一波三折:剛拿到項目要求時認為只是項目二的網店+LINUX操作系統,very easy;中間遇到文件讀寫的bug,苦苦找不到對策,整整一周幾乎沒有進展;最后兩天靈感迸發,修復了之前的bug,并一天碼了破千行代碼,掉了滿地頭發……無論如何,項目終歸是結束了,也留給了我日后繼續學習數據庫和操作系統的基礎,再說回程設實驗,不得不說這門課耗時只能用恐怖形容,所幸下一屆學弟學妹們不用再受這苦😭
最后只想說一句:程設實驗,再nm的見!
項目介紹
本項目中我們需要在Linux環境下使用C/C++語言搭建一個最簡單、最基礎的數據庫mySQL,模擬數據庫的基本操作,實現六大類基本命令語句,待解決的問題有:
1. 如何實現Linux環境下代碼的編譯與執行(注意Linux和Windows環境下文件操作的不同);
2. 如何(使用正則表達式)解析指令,獲取不同的操作對象;
3. 如何使用文件保存各個表格的內容以及維護整個數據庫的狀態;
4….
功能實現
本項目中只要求實現一個最簡單的數據庫,也即實現六大類基本功能——
CREATE TABLE,DROP TABLE,INSERT INTO,DELETE,UPDATE,SELECT
它們對應的命令語句如下:
接下來展示部分命令功能的實現截圖:??
重要說明
- 正規數據庫的命令解析還是應當考慮正則表達式,本項目中由于時間原因直接使用原始的字符串解析方法,非常暴力,有待改進
- 為了盡可能減少bug,文件名最好采用英文
- Linux環境下可能出現小部分字符亂碼現象,但基礎功能均可正常實現
- 源碼開源 ≠ 完全開放,代碼分享僅供學習工作交流使用,嚴禁作業抄襲及商業用途
- 致謝NJU最后一屆程設實驗課的老師與助教,耐心解答了我的許多問題
接下來分享源代碼!接近兩千行,時間原因不能注釋詳盡,之后有時間爭取補上(有時間也不一定🙄)
源代碼分享
#include<iostream> #include<string> #include<fstream> using namespace std;/*一些測試指令 * TABLE LIST * CREATE TABLE Student FROM student.txt * CREATE TABLE CS_Student FROM CS.txt * CREATE TABLE Student (學號,姓名,專業) TO student.txt * CREATE TBALE Lecture (課程編號,課程名稱,任課老師) TO lecture.txt * DROP TABLE Lecture * * INSERT INTO Student VALUES (170000001,張三,計算機科學與技術) * INSERT INTO Student VALUES (170000002,李四,金融系) * INSERT INTO Student (學號,姓名) VALUES (170000003,王二) * INSERT INTO Student (學號,姓名,專業) VALUES (170000004,劉五,微電子) * * DELETE FROM Student WHERE 姓名 = 張三 * DELETE * FROM Student * * UPDATE Student SET 學號 = 170000000, 專業 = 計算機科學與技術 * UPDATE Student SET 學號 = 170000000, 專業 = 地球科學 WHERE 姓名 = 張三 * * SELECT 學號,姓名 FROM Student * SELECT * FROM Student * SELECT 專業 FROM Student * SELECT DISTINCT 專業 FROM Student * SELECT * FROM Student ORDER BY 學號 DESC * SELECT 專業 FROM Student WHERE 姓名 = 張三 * SELECT * FROM Student WHERE 姓名 = 張三 * SELECT * FROM Student WHERE 專業 = 計算機科學與技術 TO CS.txt * * SELECT * FROM Student WHERE 學號 > 170000000 * SELECT MAX(學號) FROM Student * SELECT * FROM Student WHERE 學號 < (SELECT MAX(學號) FROM Student) *//* * 這里是數據結構及函數聲明~ */ struct SQL //數據庫結構體,包括表名和文件名和表格對應序號 {string table_name;string file_name;int index; }; SQL my_sql[100]; //維護一個數據庫狀態數組 int my_sql_num = 0; //當前數據庫狀態行數struct TABLE //表格結構體,包括表名,文件名,各列的屬性名,行數列數 {string table_name;string file_name;string column[50];int col_num = 0; int row_num = 0; }; TABLE all_table[100]; //維護一個全體表格數組 int table_num = 0; //當前數據庫表格數量string table_data[100][100]; //維護一個數據二維數組,用于暫時存儲更新的表格數據 int row = 0, col = 0; //當前表格數據行列數//讀取數據庫文件 void read_my_sql();//寫入數據庫文件 void write_my_sql();//讀取所有表格及其屬性 void read_all_table();//讀取表頭 void read_table(int index, string filename);//寫入表頭 void write_table(int index, string filename);//讀取表格數據 void read_table_data(int index, string filename);//寫入表格數據 void write_table_data(int index, string filename);//根據指令創建表格 void Create_table(char ins[]);//根據指令刪除表格 void Drop_table(char ins[]);//查看所有表格 void Table_list();//向表格中插入數據 void Insert_table_data(char ins[]);//刪除表格數據 void Delete_table_data(char ins[]);//修改表格數據 void Updata_table_data(char ins[]);//選擇表格數據并展示 void Selete_table_data(char ins[]);//打印表格數據 void printf_table(int index);//打印所有表格列表 void printf_table_list();//判斷是否為空行(即m是否為字母) bool is_not_endl(char m);/* * 這里是主函數~ */ int main() {cout << "\033[33m-----\033[32mWelcome \033[35mto \033[36mmySQL!\033[33m-----\033[0m" << endl;while (true){cout << "(mysql)==>";char ins[100]; //用來接受指令cin.getline(ins, 100);//Quit 退出數據庫if (ins[0] == 'q'&& ins[1] == 'u'&& ins[2] == 'i'&& ins[3] == 't'){cout << "\033[33m-----\033[32mQuit \033[36mmySQL!\033[33m-----\033[0m" << endl;break;}//CREATE TABLE 創建表格功能else if (ins[0] == 'C' && ins[1] == 'R' && ins[2] == 'E' && ins[3] == 'A' && ins[4] == 'T' && ins[5] == 'E'){Create_table(ins);}//DROP TABLE 刪除表格功能 else if (ins[0] == 'D' && ins[1] == 'R' && ins[2] == 'O' && ins[3] == 'P'){Drop_table(ins);}//TABLE LIST 查看所有表格else if ((ins[0]=='0')||(ins[0] == 'T' && ins[1] == 'A' && ins[2] == 'B' && ins[3] == 'L' && ins[4] == 'E')){Table_list();}//INSERT INTO 插入數據else if (ins[0] == 'I' && ins[1] == 'N' && ins[2] == 'S' && ins[3] == 'E' && ins[4] == 'R' && ins[5] == 'T'){Insert_table_data(ins);}//DELETE 刪除數據else if (ins[0] == 'D' && ins[1] == 'E' && ins[2] == 'L' && ins[3] == 'E' && ins[4] == 'T' && ins[5] == 'E'){Delete_table_data(ins);}//UPDATE 更新數據else if (ins[0] == 'U' && ins[1] == 'P' && ins[2] == 'D' && ins[3] == 'A' && ins[4] == 'T' && ins[5] == 'E'){Updata_table_data(ins);}//SELECT 選擇數據else if (ins[0] == 'S' && ins[1] == 'E' && ins[2] == 'L' && ins[3] == 'E' && ins[4] == 'C' && ins[5] == 'T'){Selete_table_data(ins);}//ERROR 指令錯誤else{cout << "Error instruction!" << endl;}}return 0; }/* * 下面是函數的定義~ *///讀取數據庫狀態文件 void read_my_sql() {my_sql_num = 0; //讀入新狀態前先將原狀態歸零const string my_sql_filename = "my_sql.txt"; //設置數據庫狀態文件名//打開文件,若文件不存在,則創建文件ifstream in_file(my_sql_filename, ios::_Noreplace);while (in_file.peek() != EOF){in_file >> my_sql[my_sql_num].table_name;in_file >> my_sql[my_sql_num].file_name;in_file >> my_sql[my_sql_num].index;if (is_not_endl(my_sql[my_sql_num].table_name[0]) == 1)my_sql_num++;}in_file.close(); }//寫入數據庫狀態文件 void write_my_sql() {const string my_sql_filename = "my_sql.txt"; //設置數據庫狀態文件名ofstream out_file(my_sql_filename, ios::out);for (int i = 0; i < my_sql_num; i++){//表名 文件名 下標out_file << my_sql[i].table_name << " ";out_file << my_sql[i].file_name << " ";out_file << my_sql[i].index << endl;}out_file.close(); }//讀取所有表格及其屬性 void read_all_table() {table_num = 0; //表格數歸零for (int i = 0; i < my_sql_num; i++){//每讀一行數據庫信息都會得到一張表int ind = my_sql[i].index;all_table[ind].table_name = my_sql[i].table_name;all_table[ind].file_name = my_sql[i].file_name;read_table(ind, my_sql[i].file_name);if (is_not_endl(all_table[ind].file_name[0]) == 1)table_num++;} }//讀取表頭 void read_table(int index, string filename) {all_table[index].col_num = 0; //讀入表頭前先將表格列數歸零//打開文件,若文件不存在,則創建文件ifstream in_file(filename, ios::_Noreplace);string s;getline(in_file, s);int i = 0;//解析表頭while(i<s.size()){int k = 0;string str;if (s[i + k] == ' ') //規避漢字中間的兩個空格i++;while (i+k!=s.size() && s[i + k] != ' '){str += s[i + k];k++;}int c = all_table[index].col_num;all_table[index].column[c] = str;all_table[index].col_num++;i = i + k + 1;}in_file.close(); }//寫入表頭 void write_table(int index, string filename) {ofstream out_file(filename, ios::out);for (int i = 0; i < all_table[index].col_num; i++)out_file << all_table[index].column[i] << " ";out_file << endl;out_file.close(); }//讀取表格數據 void read_table_data(int index, string filename) {all_table[index].row_num = 0; //讀入表頭前先將表格行數歸零//打開文件,若文件不存在,則創建文件ifstream in_file(filename, ios::_Noreplace);//先讀表頭string s;getline(in_file, s);//剩下的是表格數據while(in_file.peek()!=EOF){for (int j = 0; j < all_table[index].col_num; j++)in_file >> table_data[all_table[index].row_num][j]; //用二維數組接受表格信息if(table_data[all_table[index].row_num][0]>="0" && table_data[all_table[index].row_num][0]<="9")all_table[index].row_num++;} in_file.close(); }//寫入表格數據 void write_table_data(int index, string filename) {ofstream out_file(filename, ios::out);//寫入表頭for (int i = 0; i < all_table[index].col_num; i++){out_file << all_table[index].column[i] << " ";}out_file << endl;//寫入數據for (int i = 0; i < all_table[index].row_num; i++){for (int j = 0; j < all_table[index].col_num; j++){out_file << table_data[i][j]<<" ";}out_file << endl;}out_file.close(); }//根據指令創建表格,獲取表名、文件名、屬性名等 void Create_table(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//解析指令獲取表名,記錄到總表格數組中string tablename;int i = 13; //移動到指令中name的第一位while (ins[i] != ' '){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;i += 1;//第一類創建語句if (ins[i] == '(') {//檢測表格名是否重復for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//表格名已存在cout << "TABLE " << tablename << " Already Exists !" << endl;return;}}//解析指令獲取每一列的屬性名,記錄到總表格數組中i += 1; //移動到指令中column[i]的第一位int k = 0;string col_name[50];col = 0;while (true){col_name[col] += ins[i + k];k++;if (ins[i + k] == ',' || ins[i + k] == ','){//把每列的名字給到對應表格的column數組中,對應列數+1int c = all_table[table_num].col_num;all_table[table_num].column[c] = col_name[col];all_table[table_num].col_num++; col++;//移動至下一個列名的第一位i = i + k + 1;k = 0;}else if (ins[i + k] == ')' || ins[i + k] == ')'){//把每列的名字給到對應表格的column數組中,對應列數+1int c = all_table[table_num].col_num;all_table[table_num].column[c] = col_name[col];all_table[table_num].col_num++; col++;i = i + k + 1;break;}}//解析指令獲取文件名,記錄到總表格數組中i += 4; //移動到指令中file的第一位string filename;while (ins[i] != '\0'){filename += ins[i];i++;}all_table[table_num].file_name = filename;//創建表格文件并寫入表頭write_table(table_num, filename);//修改數據庫狀態my_sql[my_sql_num].table_name = tablename;my_sql[my_sql_num].file_name = filename;my_sql[my_sql_num].index = table_num;my_sql_num++;write_my_sql(); //更新數據庫狀態文件table_num++; //最后,表格數量加一//展示最新創建的表頭cout << "--------------------" << endl;cout << "ID ";for (int i = 0; i < all_table[table_num - 1].col_num; i++){cout << all_table[table_num - 1].column[i] << " ";}cout << endl;cout << "--------------------" << endl;}//第二類創建語句(相當于打印已有表格)else if (ins[i] == 'F') {int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);printf_table(index);flag = 0;break;}else if (my_sql[j].table_name == "None"){//給無名氏表格命名my_sql[j].table_name = tablename;write_my_sql();index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);printf_table(index);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}}else{cout << "Error instruction!" << endl;} }//根據指令刪除表格 void Drop_table(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//解析指令獲取待刪除表名string tablename;int i = 11;while (ins[i] != '\0'){tablename += ins[i];i++;}bool flag = 1;for (int j = 0; j < my_sql_num;j++){if (my_sql[j].table_name == tablename){//找到待刪的表格,則進行數據遷移for (int k = j; k < my_sql_num-1; k++){my_sql[k].table_name = my_sql[k+1].table_name;my_sql[k].file_name = my_sql[k+1].file_name;}table_num--;my_sql_num--;flag = 0;cout << "DROP TABLE SUCCESS !" << endl;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}write_my_sql(); //更新數據庫狀態文件read_all_table(); //修改當前表格列表 }//查看所有表格 void Table_list() {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//依次讀取每張表格的數據for (int i = 0; i < table_num; i++){read_table_data(i, all_table[i].file_name);}//打印所有表格信息cout << " Total table number:" << table_num << endl;for (int i = 0; i < table_num; i++){cout << " " << all_table[i].table_name << ":";cout << "(" << all_table[i].col_num << "," << all_table[i].row_num << ")";if (all_table[i].col_num == 0)cout << "[ ]" << endl;else{cout << "[" << all_table[i].column[0];for (int j = 1; j < all_table[i].col_num; j++)cout << "," << all_table[i].column[j];cout << "]" << endl;}} }//向表格中插入數據 void Insert_table_data(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//解析指令獲取表名string tablename;int i = 12; //移動到指令中name的第一位while (ins[i] != ' '){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;//根據表名打開對應文件,讀取表格數據int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}i += 1; //第一類插入語句if (ins[i] == 'V') {i += 8; //i移動到value[i]的第一位int k = 0;string col_value[50];int num = 0;col = 0, row = all_table[index].row_num;while (true){col_value[num] += ins[i + k];k++;if (ins[i + k] == ',' || ins[i + k] == ','){//把每列的值給到對應表格的值數組中,對應列數+1table_data[row][col] = col_value[num];num++; col++;//移動至下一個值i = i + k + 1;k = 0;}else if (ins[i + k] == ')' || ins[i + k] == ')'){//把每列的值給到對應表格的值數組中,對應列數+1table_data[row][col] = col_value[num];num++; col++;i = i + k + 1;break;}}cout << "INSERT SUCCESS !" << endl;all_table[index].row_num++;printf_table(index);//修改表格文件write_table_data(index, filename);}//第二類插入語句else if (ins[i] == '(') {//獲取給定列名稱和添加的值i += 1; //i移動到column[i]的第一位int k = 0;string cols[50]; //暫存column[i]的值int num = 0; //給定值的個數while (true){cols[num] += ins[i + k];k++;if (ins[i + k] == ',' || ins[i + k] == ','){num++;//移動至下一個值i = i + k + 1;k = 0;}else if (ins[i + k] == ')' || ins[i + k] == ')'){num++;i = i + k + 1;break;}}i += 9; //i移動到value[i]的第一位k = 0;string value[50]; //暫存value[i]的值num = 0; //給定值的個數while (true){string col_value;value[num] += ins[i + k];k++;if (ins[i + k] == ',' || ins[i + k] == ','){num++;//移動至下一個值i = i + k + 1;k = 0;}else if (ins[i + k] == ')' || ins[i + k] == ')'){num++;i = i + k + 1;break;}}col = 0, row = all_table[index].row_num;for (int m = 0; m < all_table[index].col_num; m++){bool tag = 1; //表示是否為缺省for (int n = 0; n < num; n++){if (all_table[index].column[m] == cols[n]){table_data[row][m] = value[n];tag = 0;break;}}if (tag == 1)table_data[row][m] = "空"; //缺省值默認為空}cout << "INSERT SUCCESS !" << endl;all_table[index].row_num++;printf_table(index);//修改表格文件write_table_data(index, filename);}else{cout << "Error instruction!" << endl;} }//刪除表格數據 void Delete_table_data(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//第一類刪除語句if (ins[7] == 'F'){//解析指令獲取表名string tablename;int i = 12; //移動到指令中name的第一位while (ins[i] != ' '){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;//讀取表格數據 int index;string filename;bool flag = 1; for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}i += 7; //i移動到待刪除的column第一位string column;while (ins[i] != ' '){column += ins[i];i++;}i += 3; //i移動到待刪除的value第一位string value;while (ins[i] != '\0'){value += ins[i];i++;}col = all_table[index].col_num, row = all_table[index].row_num;//先找到刪除的列的下標int column_index = -1;for (int k = 0; k < col; k++){if (all_table[index].column[k] == column){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}bool tag = 1;//再逐行搜索滿足條件的記錄for (int k = 0; k < row; k++){if (table_data[k][column_index] == value){tag = 0;//找到待刪行,進行數據遷移for (int m = k; m < row - 1; m++){for (int n = 0; n < col; n++){table_data[m][n] = table_data[m + 1][n];}}break;}}if (tag == 1){cout << "Error instruction!" << endl;return;}else{all_table[index].row_num--;cout << "DELETE SUCCESS !" << endl;printf_table(index);//修改表格文件write_table_data(index, filename);}}//第二類刪除語句else if (ins[7] == '*' && ins[9]=='F'){//解析指令獲取表名string tablename;int i = 14; //移動到指令中name的第一位while (ins[i] != '\0'){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;//讀取表格數據 int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}all_table[index].row_num = 0; //刪除所有行cout << "DELETE SUCCESS !" << endl;printf_table(index);//修改表格文件write_table_data(index, filename);}else{cout << "Error instruction!" << endl;} }//修改表格數據 void Updata_table_data(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();//解析指令獲取表名string tablename;int i = 7; //移動到指令中name的第一位while (ins[i] != ' '){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;//根據表名打開對應文件,讀取表格數據int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}i += 5; //移動到column i第一位int k = 0;int tag = 0;string s[50];string column[50], value[50];int num = 0;while (true){while (ins[i + k] != ','&& ins[i + k] != '\0'&&ins[i + k] != 'W'){s[num] += ins[i + k];k++;}if (ins[i + k] == ','){num++;i = i + k + 2;k = 0;}else if (ins[i + k] == '\0'){tag = 1; //第一類更新語句num++;break;}else if (ins[i + k] == 'W'){tag = 2; //第二類更新語句num++;//最后一句多了一個空格,刪去之string temp = s[num - 1].substr(0, s[num - 1].size() - 1);s[num - 1] = temp;i = i + k + 6; //i 移動到column首位break;}}//逐句再次解析for (int j = 0; j < num; j++){int cur = 0;while (s[j][cur] != ' ')cur++;column[j] = s[j].substr(0, cur);cur += 3;value[j] = s[j].substr(cur, s[j].size());}if (tag == 1){//對表格每一列進行遍歷,搜索column[]數組判斷是否需要更改for (int j = 0; j < all_table[index].col_num; j++){for (int n = 0; n < num; n++){if (all_table[index].column[j] == column[n]) {//更改這一列每一行的值for (int m = 0; m < all_table[index].row_num; m++){//m是表格的某一行,j是表格的某一列,n是對應要修改的值table_data[m][j] = value[n];}break;}}}cout << "UPDATE SUCCESS !" << endl;printf_table(index);//修改表格文件write_table_data(index, filename);}else if (tag == 2){//記錄限制條件 column = valuestring clmn, val;while (ins[i] != ' '){clmn += ins[i];i++;}i += 3;while (ins[i] != '\0'){val += ins[i];i++;}//找到對應的列的下標int column_index = -1;for (k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == clmn){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}//對表格每一列進行遍歷,搜索column[]數組判斷是否需要更改for (int j = 0; j < all_table[index].col_num; j++){for (int n = 0; n < num; n++){if (all_table[index].column[j] == column[n]){//只更改這一列滿足限制條件的行的值for (int m = 0; m < all_table[index].row_num; m++){//判斷是否滿足條件if (table_data[m][column_index] == val){//m是表格的某一行,j是表格的某一列,n是對應要修改的值table_data[m][j] = value[n];}}break;}}}cout << "UPDATE SUCCESS !" << endl;printf_table(index);//修改表格文件write_table_data(index, filename);}else{cout << "Error instruction!" << endl;} }//選擇表格數據并展示 void Selete_table_data(char ins[]) {//先讀取數據庫狀態文件和現有表格列表read_my_sql();read_all_table();if (ins[7] == '*'){//解析指令獲取表名string tablename;int i = 14; //移動到指令中name的第一位while (ins[i] != '\0' && ins[i] != ' '){tablename += ins[i];i++;}//根據表名打開對應文件,讀取表格數據int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}//從TABLE name里選擇所有列展示,即展示整個TABLEif (ins[i] == '\0'){printf_table(index);}//對返回的查詢結果按某些列進行排序展示else if (ins[i] == ' ' && ins[i + 1] == 'O'){i += 10; //移動到 column i 第一位string column[50];int num = 0;int k = 0;while (true){while (ins[i + k] != ',' && ins[i + k] != ' '){column[num] += ins[i + k];k++;}if (ins[i + k] == ','){num++;i = i + k + 1;k = 0;}else if (ins[i + k] == ' '){num++;i = i + k + 1; //i 移動到ASC|DESC首位break;}}//找到對應的列的下標int column_index = -1;for (k = 0; k < all_table[index].col_num; k++){//支持按某一列的值排序if (all_table[index].column[k] == column[0]){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}if (ins[i] == 'A') //升序{for (int m = 0; m < all_table[index].row_num - 1; m++){for (int n = 0; n < all_table[index].row_num - m - 1; n++){if (table_data[n][column_index] > table_data[n + 1][column_index]){//交換兩行元素for (int tt = 0; tt < all_table[index].col_num; tt++){string temp = table_data[n][tt];table_data[n][tt] = table_data[n + 1][tt];table_data[n + 1][tt] = temp;}}}}}else if (ins[i] == 'D') //降序{for (int m = 0; m < all_table[index].row_num - 1; m++){for (int n = 0; n < all_table[index].row_num - m - 1; n++){if (table_data[n][column_index] < table_data[n + 1][column_index]){//交換兩行元素for (int tt = 0; tt < all_table[index].col_num; tt++){string temp = table_data[n][tt];table_data[n][tt] = table_data[n + 1][tt];table_data[n + 1][tt] = temp;}}}}}else{cout << "Error instruction!" << endl;return;}//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}else if (ins[i] == ' ' && ins[i + 1] == 'W'){i += 7; //i 移動到column第一位//記錄限制條件 column = valuestring clmn, val;while (ins[i] != ' '){clmn += ins[i];i++;}i += 1;// column = valueif (ins[i] == '='){i += 2;while (ins[i] != '\0' && ins[i] != ' '){val += ins[i];i++;}//找到對應的列的下標int column_index = -1;for (int k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == clmn){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}if (ins[i] == '\0'){//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){if (table_data[m][column_index] == val){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}}else{i += 4; //移動到新表格文件名第一位string new_filename;while (ins[i] != '\0'){new_filename += ins[i];i++;}//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){if (table_data[m][column_index] == val){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}//創建新表寫入文件ofstream out_file(new_filename, ios::out);//寫入表頭for (int j = 0; j < all_table[index].col_num; j++){out_file << all_table[index].column[j] << " ";}out_file << endl;//寫入數據for (int m = 0; m < all_table[index].row_num; m++){if (table_data[m][column_index] == val){for (int n = 0; n < all_table[index].col_num; n++){out_file << table_data[m][n] << " ";}out_file << endl;}}out_file.close();//修改數據庫狀態my_sql[my_sql_num].table_name = "None";my_sql[my_sql_num].file_name = new_filename;my_sql[my_sql_num].index = table_num;my_sql_num++;write_my_sql(); //更新數據庫狀態文件}}// column > valueelse if (ins[i] == '>'){i += 2;while (ins[i] != '\0'){val += ins[i];i++;}//找到對應的列的下標int column_index = -1;for (int k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == clmn){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){if (table_data[m][column_index] > val){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}}// column < value ,其中value=max(學號)else if (ins[i] == '<'){i += 2;//找到對應的列的下標int column_index = -1;for (int k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == clmn){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}//找學號最大值string max = table_data[0][column_index];for (int j = 0; j < all_table[index].row_num; j++){if (table_data[j][column_index] > max){max = table_data[j][column_index];}}//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){if (table_data[m][column_index] < max){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}}else{cout << "Error instruction!" << endl;return;}}else{cout << "Error instruction!" << endl;}}else if (ins[7] == 'D'){string column[50];int num = 0;int i = 16; //移動到 column i 第一位int k = 0;while (true){while (ins[i + k] != ',' && ins[i + k] != ' '){column[num] += ins[i + k];k++;}if (ins[i + k] == ','){num++;i = i + k + 1;k = 0;}else if (ins[i + k] == ' '){num++;i = i + k + 6; //i 移動到name首位break;}}//解析表名string tablename;while (ins[i] != '\0' && ins[i] != ' '){tablename += ins[i];i++;}//根據表名打開對應文件,讀取表格數據int index;string filename;bool tag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);tag = 0;break;}}if (tag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}bool flag[50]; //給每一列做標記for (int j = 0; j < all_table[index].col_num; j++){flag[j] = 0;}for (int j = 0; j < all_table[index].col_num; j++){for (k = 0; k < num; k++){if (all_table[index].column[j] == column[k]){flag[j] = 1;break;}}}//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){if (flag[j] == 1)cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){bool print = 1; //判斷要不要打印 for (int n = 0; n < all_table[index].col_num; n++){if (flag[n] == 1){for (int a = 0; a < m; a++){if (table_data[a][n] == table_data[m][n]){print = 0;break;}}}}if (print == 1){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){if (flag[n] == 1)cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}}else if (ins[7] == 'M'){int i = 11; string column;while (ins[i] != ')'){column += ins[i];i++;}//解析指令獲取表名i += 7;string tablename;while (ins[i] != '\0'){tablename += ins[i];i++;}//根據表名打開對應文件,讀取表格數據int index;string filename;bool flag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);flag = 0;break;}}if (flag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}//找到對應的列的下標int column_index = -1;for (int k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == column){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}//找最大值int maxline = 0;string max = table_data[0][column_index];for (int j = 0; j < all_table[index].row_num; j++){if (table_data[j][column_index] > max){max = table_data[j][column_index];maxline = j;}}//打印//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據cout << maxline + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){cout << table_data[maxline][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}else{string column[50];int num = 0;int i = 7; //移動到 column i 第一位int k = 0;while (true){while (ins[i + k] != ',' && ins[i + k] != ' '){column[num] += ins[i + k];k++;}if (ins[i + k] == ','){num++;i = i + k + 1;k = 0;}else if (ins[i + k] == ' '){num++;i = i + k + 6; //i 移動到name首位break;}}//解析表名string tablename;while (ins[i] != '\0' && ins[i] != ' '){tablename += ins[i];i++;}all_table[table_num].table_name = tablename;//根據表名打開對應文件,讀取表格數據int index;string filename;bool tag = 1;for (int j = 0; j < my_sql_num; j++){if (my_sql[j].table_name == tablename){//找到了對應的表格index = my_sql[j].index;filename = my_sql[j].file_name;read_table_data(index, filename);tag = 0;break;}}if (tag == 1) //沒找到{cout << "Not found TABLE " << tablename << " !" << endl;return;}bool flag[50]; //給每一列做標記for (int j = 0; j < all_table[index].col_num; j++){flag[j] = 0;}for (int j = 0; j < all_table[index].col_num; j++){for (k = 0; k < num; k++){if (all_table[index].column[j] == column[k]){flag[j] = 1;break;}}}//從TABLE name里選擇若干列展示if (ins[i] == '\0'){//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){if(flag[j]==1)cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){if (flag[n] == 1)cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}//從TABLE name里選擇若干列展示else if (ins[i] == ' ' && ins[i + 1] == 'W'){i += 7; //移動到column首位//記錄限制條件 column = valuestring clmn, val;while (ins[i] != ' '){clmn += ins[i];i++;}i += 3;while (ins[i] != '\0'){val += ins[i];i++;}//找到對應的列的下標int column_index = -1;for (k = 0; k < all_table[index].col_num; k++){if (all_table[index].column[k] == clmn){column_index = k;break;}}if (column_index == -1){cout << "Error instruction!" << endl;return;}//打印表頭cout << "----------------------------------------" << endl;cout << "ID ";for (int j = 0; j < all_table[index].col_num; j++){if (flag[j] == 1)cout << all_table[index].column[j] << " ";}cout << endl;cout << "----------------------------------------" << endl;//打印數據for (int m = 0; m < all_table[index].row_num; m++){if(table_data[m][column_index]==val){cout << m + 1 << " ";for (int n = 0; n < all_table[index].col_num; n++){if (flag[n] == 1)cout << table_data[m][n] << " ";}cout << endl;cout << "----------------------------------------" << endl;}}}else{cout << "Error instruction!" << endl;}} }//打印表格 void printf_table(int index) {cout << "----------------------------------------" << endl;cout << "ID ";for (int i = 0; i < all_table[index].col_num; i++){cout << all_table[index].column[i] << " ";}cout << endl;cout << "----------------------------------------" << endl;for (int i = 0; i < all_table[index].row_num; i++){cout << i + 1 << " ";for (int j = 0; j < all_table[index].col_num; j++)cout << table_data[i][j] << " ";cout << endl;cout << "----------------------------------------" << endl;} }//打印所有表格列表 void printf_table_list() {for (int i = 0; i < table_num; i++)cout << all_table[i].table_name << " " << all_table[i].file_name << endl; }//判斷是否為空行(即m是否為字母) bool is_not_endl(char m) {if (((m >= 'a') && (m <= 'z')) || ((m >= 'A') && (m <= 'Z')))return true;return false; }寫在最后
項目來源不易,能看到這里的話點個贊再走吧~
如有疑問,可聯系QQ:450112427,備注說明來意
總結
以上是生活随笔為你收集整理的【项目源码分享】基于C++实现的小型数据库(Windows/Linux环境)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【项目源码分享】基于C++实现的网店购物
- 下一篇: Linux下Anaconda3安装及使用