Cpp-实现一个数据库系统
我会在这里更新关于这个项目我的想法、实现、遇到的问题,以及更新版本.
==============================================================================
2021-5-14 版本1.0
==============================================================================
目前已实现的功能如下图

大概思路为:
getline获取指令->把字符串按空格分解成单词->进行对应的操作
输入exit退出->程序把所有的数据写入文本,命名格式为 数据库名_表名_行数_列数.txt
在程序打开时先进行初始化->从tableLibrary.txt文件中读取出所有的文件名,该建库建库、该建表建表,然后将数据存入
下一版本:
1.保留原功能
2.用vector来存放表和数据库
3.完善操作指令匹配(要求更严谨) 以及 错误操作时的反馈
4.完善与用户沟通的提示(该做什么?错误提示?操作成功?)
5.给代码增加异常处理
6.优化代码
以下是该版本代码:
主程序 DBS.cpp
#include<iostream> #include<string> #include<fstream> #include"Database.h" using namespace std; Database* database = new Database[5];//最多用5个数据库 int databaseCount = 0;//用于记录数据库的数量 int databaseSign = -1;//用于标记当前使用的数据库 string convertCase(string a); void CreateTable(string fileName); void CreateDatabase(string databaseName); void Init(); int main() { string instruct;//用于接收指令 bool run = true;//用于控制程序运行 string a[100]; int aCount = 0; cout << "==========================================================================================" << '\n'; cout << "欢迎您使用本数据库系统" << '\n'; cout << "1、建立数据库输入 :create database 数据库名" << '\n'; cout << "2、使用数据库请输入 :use 数据库名" << '\n'; cout << "3、创建表请输入 :create table 表名 (字段名)" << '\n'; cout << "4、展示所有表请输入 :show tables" << '\n'; cout << "5、删除表请输入 :drop table 表名" << '\n'; cout << "6、向表中插入数据请输入 :insert into 表名 values (值)" << '\n'; cout << "7、查找表中数据请输入 :select 字段名 from 表名 where 条件" << '\n'; cout << "8、修改表中数据请输入 :update 表名 set 字段名=值 where 条件" << '\n'; cout << "9、删除表中满足条件的行请输入 :delete from 表名 where 条件" << '\n'; cout << "10、修改表结构请输入 :alter table 表名 add|drop 列名" << '\n'; cout << "11、退出数据库系统请输入 :exit" << '\n'; cout << "12、查看并使用历史指令请输入history" << '\n'; cout << "==========================================================================================" << '\n'; Init(); while (run) { cout << "sql>"; while (1) { getline(cin, instruct); if (instruct != "") { break; } } a[aCount] = instruct; aCount++; if (instruct == "history") { for (int i = 0; i < aCount; i++) { cout << i << " " << a[i] << endl; } cout << "请输入标号:"; int sign; cin >> sign; instruct = a[sign]; } instruct = convertCase(instruct); string insArr[7] = { "" }; int insArrCount = 0; for (int i = 0; i < instruct.length(); i++) { if (instruct[i] != ' ') { insArr[insArrCount] += instruct[i]; } else { insArrCount++; } } if (instruct == "exit") { run = false; for (int i = 0; i < databaseCount; i++) { if (database[i].getDatabaseName() != "") { database[i].tableInFile(); } } continue; } if (insArr[0] == "create" && insArr[1] == "database") { Database db(insArr[2]); databaseCount++; database[databaseCount - 1] = db; continue; } if (insArr[0] == "show" && insArr[1] == "database") { for (int i = 0; i < databaseCount; i++) { if (database[i].getDatabaseName() != "") { cout << database[i].getDatabaseName() << endl; } } continue; } if (insArr[0] == "use") { for (int i = 0; i < databaseCount; i++) { if (database[i].getDatabaseName() == insArr[1]) { databaseSign = i; } } cout << "正在使用" << database[databaseSign].getDatabaseName() << "数据库" << '\n'; continue; } if (databaseSign == -1) { cout << "操作者没有选择需要操作的数据库" << '\n'; continue; } if (insArr[0] == "create" && insArr[1] == "table") { database[databaseSign].createTable(insArr[2], insArr[3]); cout << "表" << insArr[2] << "创建成功" << '\n'; continue; } if (insArr[0] == "show" && insArr[1] == "tables") { database[databaseSign].showTables(); continue; } if (insArr[0] == "drop") { database[databaseSign].dropTable(insArr[2]); continue; } if (insArr[0] == "insert") { database[databaseSign].insertValue(insArr[2], insArr[4]); continue; } if (insArr[0] == "select") { database[databaseSign].selectValue(insArr[1], insArr[3], insArr[5]); continue; } if (insArr[0] == "update") { database[databaseSign].updateValue(insArr[1], insArr[3], insArr[5]); continue; } if (insArr[0] == "delete") { database[databaseSign].deleteValue(insArr[2], insArr[4]); continue; } if (insArr[0] == "alter" && insArr[1] == "table") { database[databaseSign].alterTable(insArr[2], insArr[3], insArr[4]); } } } string convertCase(string a) { for (int i = 0; i < a.length(); i++) { if (a[i] >= 'A' && a[i] <= 'Z') { a[i] += 32; } } return a; } void CreateTable(string fileName) { database[databaseSign].createTable(fileName); } void CreateDatabase(string databaseName) { for (int i = 0; i < databaseCount; i++) { if (database[i].getDatabaseName() == databaseName) { return; } } databaseCount++; Database db(databaseName); database[databaseCount - 1] = db; } void Init() { string nameArr[25]; int count = 0; ifstream f_in; f_in.open("tableLibrary.txt", ios::in); while (f_in >> nameArr[count]) count++; for (int i = 0; i < count; i++) { string fileName = nameArr[i]; string splitArr[4]; int splitArrCount = 0; for (int j = 0; j < fileName.length(); j++) { if (fileName[j] == '.') break; if (fileName[j] != '_') { splitArr[splitArrCount] += fileName[j]; } else { splitArrCount++; } } CreateDatabase(splitArr[0]); for (int i = 0; i < databaseCount; i++) { if (database[i].getDatabaseName() == splitArr[0]) { databaseSign = i; } } CreateTable(fileName); } f_in.close(); f_in.clear(); ofstream f_out; f_out.open("tableLibrary.txt", ios::out); f_out << ""; f_out.close(); f_out.clear(); }
头文件 Table.h
#pragma once #include<iostream> #include<string> #include<fstream> using namespace std; int transition(string a); string transition(int a); class Table { private: string databaseName; //数据库名 string tableName; //表的名字 string data[101][10] = { "" }; //最大100行,10列的数据表 int cow; //行的总数 int column; //列的总数 void proFieldNames(string fieldName); //建表时处理字段名 int seekColNum(string colName); //查找名叫colName的列号 int seekCowNum(string condition); //根据条件condition来返回满足条件的行号 public: Table(string databaseName,string name,string fieldName); //正常的有参的构造函数 Table(string fileName); //初始化的构造函数 Table(); //无参的构造函数 string getTableName(); //返回表名 void getTableData(); //输出整个表 void insertData(string fieldValue); //插入数据----只支持插入一次全部字段 void deleteData(string condition); //删除数据----只支持单条件 void updateData(string newValue, string condition); //修改数据----只支持单条件修改单个值 void selectData(string fieldName, string condition); //查询数据----只支持单条件查询 void dropTable(); //删除表 void inFile(); //写入文件 void alterTable(string order, string colName); //修改表结构 }; Table::Table(string databaseName,string name,string fieldName) { this->databaseName = databaseName; tableName = name; cow = 1; column = 1; proFieldNames(fieldName); } Table::Table(string fileName) { string splitArr[4]; int splitArrCount = 0; for (int j = 0; j < fileName.length(); j++) { if (fileName[j] == '.') break; if (fileName[j] != '_') { splitArr[splitArrCount] += fileName[j]; } else { splitArrCount++; } } databaseName = splitArr[0]; tableName = splitArr[1]; cow = transition(splitArr[2]); column = transition(splitArr[3]); ifstream f_in; f_in.open(fileName, ios::in); for (int i = 0; i < cow; i++) { for (int j = 0; j < column; j++) { f_in >> data[i][j]; } } f_in.close(); } void Table::proFieldNames(string fieldName) { for (int i = 0; i < fieldName.length(); i++) { if (fieldName[i] != '(' && fieldName[i] != ')') { if (fieldName[i] != ',') data[0][column-1] += fieldName[i]; else column++; } } } Table::Table() { tableName = ""; cow = 0; column = 0; } string Table::getTableName() { return tableName; } void Table::getTableData() { for (int i = 0; i < 40; i++) cout << "="; cout << '\n'; for (int i = 0; i < cow; i++) { for (int j = 0; j < column; j++) { if (data[i][j] != "") { if (j == 0) cout << "||" << '\t'; cout << data[i][j] << '\t' << "||" << '\t'; } } cout << '\n'; } for (int i = 0; i < 40; i++) cout << "="; cout << '\n'; } void Table::insertData(string fieldValue) { cow++; int col = 0; for (int i = 0; i < fieldValue.length(); i++) { if (fieldValue[i] != '(' && fieldValue[i] != ')') { if (fieldValue[i] != ',') { data[cow - 1][col] += fieldValue[i]; } else { col++; } } } } int Table::seekColNum(string colName) { for (int i = 0; i < column; i++) if (data[0][i] == colName) return i; } int Table::seekCowNum(string condition) { string strArr[2]; int count = 0; for (int i = 0; i < condition.length(); i++) { if (condition[i] != '=') { strArr[count] += condition[i]; } else { count++; } } int colNum = seekColNum(strArr[0]); for (int i = 1; i < cow; i++) { if (data[i][colNum] == strArr[1]) { return i; } } } void Table::deleteData(string condition) { int cowNum = seekCowNum(condition); for (int j = 0; j < column; j++) { data[cowNum][j] = ""; } } void Table::updateData(string newValue, string condition) { string valueArr[2]; int countValueArr = 0; for (int i = 0; i < newValue.length(); i++) { if (newValue[i] != '=') { valueArr[countValueArr] += newValue[i]; } else { countValueArr++; } } int valueColNum = seekColNum(valueArr[0]); int condCowNum = seekCowNum(condition); data[condCowNum][valueColNum] = valueArr[1]; } void Table::selectData(string fieldName, string condition) { string fieldNameaArr[10]; int fieldNameNum = 0; for (int i = 0; i < fieldName.length(); i++) { if (fieldName[i] != ',') { fieldNameaArr[fieldNameNum] += fieldName[i]; } else { fieldNameNum++; } } int cowNum = seekCowNum(condition); for (int i = 0; i <= fieldNameNum; i++) { cout << data[0][seekColNum(fieldNameaArr[i])] << '\t'; } cout << '\n'; for (int i = 0; i <= fieldNameNum; i++) { cout << data[cowNum][seekColNum(fieldNameaArr[i])] << '\t'; } cout << '\n'; } void Table::dropTable() { tableName = ""; for (int i = 0; i < cow; i++) { for (int j = 0; j < column; j++) { data[i][j] = ""; } } cow = 0; column = 0; } void Table::inFile() { fstream f_out; string COW = transition(cow); string COL = transition(column); string name = databaseName + '_' + tableName + '_' + COW + '_' + COL + ".txt"; f_out.open(name.c_str(), ios::out); for (int i = 0; i < cow; i++) { for (int j = 0; j < column; j++) { f_out << data[i][j]; f_out << '\t'; } f_out << '\n'; } f_out.clear(); fstream f_out1; f_out1.open("tableLibrary.txt", ios::app | ios::out); f_out1 << name; f_out1 << '\n'; } void Table::alterTable(string order, string colName) { if (order == "add") { column++; data[0][column-1] = colName; for (int i = 1; i < cow; i++) { data[i][column - 1] = " "; } } else if (order == "drop") { int colNumber = seekColNum(colName); for (int i = colNumber; i < column; i++) { for (int j = 0; j < cow; j++) { if (i == column - 1) data[j][i] = ""; else data[j][i] = data[j][i + 1]; } } column--; } } int transition(string a) { int ans = 0; for (int i = 0; i < a.length(); i++) { ans = ans * 10 + (a[i] - '0'); } return ans; } string transition(int a) { string ans; while (a != 0) { char s = a % 10 + '0'; ans = s + ans; a /= 10; } return ans; }
头文件 Database.h
#pragma once #include<iostream> #include<string> #include"Table.h" using namespace std; class Database { private: string databaseName; //库的名字 int tableCount; //数据库中表的数量 Table* table = new Table[5]; //Table数组 int seekTable(string tableName); //返回名为tableName的表的下标 public: Database(string name); //有参的构造函数 Database(); //无参的构造函数 void createTable(string tableName,string fieldName); //创建一个表 void createTable(string fileName); void showTables(); //打印所有表 void dropTable(string tableName); //删除名为tableName的表 void deleteValue(string tableName, string condition); //删除表中满足条件的行 void insertValue(string tableName, string fieldValue); //插入数据 void selectValue(string fieldName, string tableName, string condition); //查询 void updateValue(string tableName, string newValue, string condition); //修改数据 string getDatabaseName(); //返回数据库名 void tableInFile(); //写入文件 void alterTable(string tableName,string order, string colName); //修改表结构 }; Database::Database(string name) { databaseName = name; tableCount = 0; } Database::Database() { databaseName = ""; tableCount = 0; } void Database::createTable(string tableName,string fieldName) { Table tab(databaseName,tableName, fieldName); tableCount++; table[tableCount - 1] = tab; } void Database::createTable(string fileName) { Table tab(fileName); tableCount++; table[tableCount - 1] = tab; } void Database::showTables() { int effectiveCount = 0; for (int i = 0; i < tableCount; i++) { if (table[i].getTableName() != "") { effectiveCount++; } } cout << "数据库" << databaseName << "一共有" << effectiveCount << "个表" << '\n'; for (int i = 0; i < tableCount; i++) { if (table[i].getTableName() != "") { effectiveCount++; table[i].getTableData(); } } } int Database::seekTable(string tableName) { for (int i = 0; i < tableCount; i++) { if (table[i].getTableName() == tableName) return i; } return -1; } void Database::dropTable(string tableName) { int tableSign = seekTable(tableName); if (tableSign == -1) { cerr << "该表不存在" << endl; return; } table[tableSign].dropTable(); } void Database::deleteValue(string tableName, string condition) { int tableSign = seekTable(tableName); table[tableSign].deleteData(condition); } void Database::insertValue(string tableName, string fieldValue) { int tableSign = seekTable(tableName); table[tableSign].insertData(fieldValue); } void Database::selectValue(string fieldName, string tableName, string condition) { int tableSign = seekTable(tableName); table[tableSign].selectData(fieldName, condition); } void Database::updateValue(string tableName, string newValue, string condition) { int tableSign = seekTable(tableName); table[tableSign].updateData(newValue, condition); } string Database::getDatabaseName() { return databaseName; } void Database::tableInFile() { for (int i = 0; i < tableCount; i++) { if (table[i].getTableName() != "") { table[i].inFile(); } } } void Database::alterTable(string tableName, string order, string colName) { int sub = seekTable(tableName); table[sub].alterTable(order, colName); }
==============================================================================
1.0 -结束
==============================================================================

浙公网安备 33010602011771号