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 -结束

==============================================================================

 

posted @ 2021-05-13 23:04  喃南瓜  阅读(141)  评论(1)    收藏  举报