C++程设实验项目二:用正则表达式制作一个简易的SQL系统

本文将尽可能简单地概括如何搭起这个SQL系统的框架。

一、正则表达式分析语句

首先需要使用c++的regex库:

#include <regex>

推荐到菜鸟教程上了解正则表达式的最基础语法。

然后,新建一个表达式。假定现在要分析的语句是CREATE TABLE (col1,col2,...) TO filename

regex r("CREATE TABLE \\((.+)\\) TO ([^ ]+)");

注意,在c++中还要转义一次反斜杠,所以一般的像\w, \(这样的符号都要写成\\w, \\(的形式。

然后用regex_match匹配一个string对象。

string cmd="CREATE TABLE (name,score) TO rec.txt";
smatch m;
if(regex_match(cmd,m,r)){
    //...
}
else cout << "NOT MATCH!" << endl;

如果cmd的内容与r匹配成功,那么结果将会保存在m里面。

那么怎么利用m的内容呢?举个例子,输出m的内容(for里面的auto这个用法也是c++11才有的)

for(auto x:m) cout << m << endl;
//result:
//CREATE TABLE (name,score) TO rec.txt     //即m.str(0),匹配到的整个式子
//name,score                               //即m.str(1),即用n个括号保存的信息,都依次保存在m的1~n个位置中//rec.txt                                  //即m.str(2)

将m.str(1)保存之后,如何处理它呢?万一这是一个很长的col1,col2,col3,...,col99的长字符串呢?这就要用到regex_search了。

regex c("([^,]+)");
string cols=m.str(1);
while(regex_search(cols,m,c)){ //确保m的文件路径信息已经被保存了
    //保存m.str(0)的信息……
    cols=m.suffix().str();
    //m.str(0): col1
    //m.suffix(): ,col2,col3,...,col99
}

regex_search会在整个字符串中寻找第一个匹配正则表达式的字串。然后,这个字串之前的部分保存在m.prefix(),之后的部分保存在m.suffix()。只要把已经查找到的字串截去,就可以再在后面的串里搜索了。

再举个例子吧:

regex r("glim");
string s="starlightglimmer";
smatch m;
regex_search(s,m,r);
//m.str(0)=="glim"
//m.prefix()=="starlight"
//m.suffix()=="mer"

由此,只要灵活地运用正则表达式,就可以很轻松地分析各种语句了。即使是有多个可选的命令,例如SELECT * FROM table [WHERE col = name] [ORDER BY col DESC] [TO file],你可以将前面的必填命令和后面三个可选参数拆成四个正则表达式,然后运用regex_search完成各种命令的分析。

二、数据结构与排序

注意,由于各人的数据结构存在差异,所以这部分不是这么通用。首先,一个表格是二维的,这就可以使用一个vector的vector来储存表格。具体我是这样操作的:

struct column {
    vector<string> item;
    string name;
};
class table {
public:
    vector<column> col;
    string tablename;
    table(string);
};

table其实当成结构体用,所以都public。

一个表的行数可以从它其中一个列里得知,同时你可以要求表名与文件名相同来节省一个string变量。

构造函数的string就是方便设置tablename用的,你也可以把它拆出来,然后写成一个结构体。

此外,在内存里,你不必储存任何一个静态的表格:毕竟是从文件读取的,只要确保要操作的表格曾经通过CREATE TABLE记录在一个vector<string> tablelist这样的地方就行了。

那么,如何对一个行操作呢?平常可以用下标来操作,但是排序怎么解决?这里提供一个思路:

例如,存在这些列:name, score, note

要对score排序整个表,可以用pair<int, string>这样的数据结构。

//table t(...)
//...
string tarcol="score";
vector<pair<int ,string>> tar;
for(auto c:t.col){
    if(c.name==tarcol){
        for(int i=0;i<c.item.size();i++){
            tar.push_back(make_pair(i,c.item[i]));
        }
    }
}

然后用<algorithm>自带的sort,同时配以自定义的cmp函数:

bool cmp(const pair &a, const pair &b) {
    int res = a.second.compare(b.second);
    if (res < 0) return true;
    else return false;
}

那么你就得到了一个排序过的pair序列。pair的数字,就是一种索引。

把当前的表一行一行地,根据索引指定的顺序塞进一个临时的新表(比如,序列的第一个索引数字是2,就把第二行的内容塞进表)。

最后,把新表复制会源表,就大功告成了。

三、文件的读取

可以考虑配合fstream,先用getline,再用流输入。具体操作:

#include <fstream>
int readtable(table &t) {
    ifstream in;
    char a[300];
    string line;
    column tmpc;

    in.open((t.tablename + ".txt").c_str());
    if (!in.is_open()) {
        //printf("Doc is not exist...\n");
        return -1;
    }
    in.getline(a, 299);
    line = a;

    smatch m;
    while (regex_search(line, m, divideSpace)) {
        tmpc.name = m.str(1);
        t.col.push_back(tmpc);
        line = m.suffix().str();
    }

    while (!in.eof()) {
        for (auto &c : t.col) {
            in >> line;
            c.item.push_back(line);
        }
    }
    for (auto &c : t.col) c.item.pop_back(); //delete invalid line
    in.close();
    return 1;
}

要注意的是,一般读取的时候是会多读一行的,这时候要把这多读的一行移除。此外,正则表达式就留给读者自己写了。

输出自然不难了。通过这种方法,可以每次都从文件读取表,然后再储存表,再退出。

四、表格分割线的绘制

这个其实不是难点,毕竟只要用一个vector<int>记录下一列的最长字串的长度,就可以轻松绘制了。

但是这里有一个坑:在Linux下,一个汉字占三个长度,然后实际显示只有两个。所以在计算长度的时候,需要进行一些处理。

具体来说,可以这么取巧:

int calLength(string s){
    double len=0;
    for(auto ch:s){
        if(0<=ch||ch<=127) len+=1;
        else len+=2.0/3;
    }
    return (int)len;
}

以上。感谢阅读。

原文地址:https://www.cnblogs.com/KakagouLT/p/9032930.html

时间: 2024-07-30 20:08:56

C++程设实验项目二:用正则表达式制作一个简易的SQL系统的相关文章

Java实验项目二——打印某年某月日历

Program:打印万年历(输入年份,月份,输出该月的日历,已知1900年1月1日是星期一), 要 求: (1)编写一个方法判断闰年: (2)编写一个方法判断某年某月有多少天: (3)编写一个方法计算某年某月前距离1900年1月1日的总天数:(4)编写一个输出某年某月日历的方法: (5)编写一个测试方法. Description:该项目由多个类实现,最后类为main方法的调用.代码如下: 1 /* 2 *Description:定义工具类 3 * 4 * */ 5 6 package tools

Java实验项目二——二维数组实现九九乘法表

Program:打印乘法口诀表 (1)编写一个方法,参数(二维数组),完成将二维数组中的数据按照行列显示的工作. (2)编写一个测试方法,给出99乘法表,放入到二维数组中,调用(1)中的方法,显示乘法口诀表. Description:main方法所在类在最后给出,代码如下: 1 /* 2 *Description:定义工具类,负责初始化二维数组和打印二维数组 3 * 4 * */ 5 6 package tools; 7 8 9 public class Operate { 10 11 //初始

Java实验项目二打印万年历

package _____;import java.util.Scanner;public class wnl//万年历主类{    public static void main(String[] args)    {                menu();        Scanner sc=new Scanner(System.in);        int menu=sc.nextInt();        if(menu==1)        {            Syste

Java实验项目二——小学生考试系统(简单四则运算)

Program:设计实现一个小学生数学考试系统,完成随机出题(简单的四则运算),学生答题,自动判分的功能. Description:代码如下: 1 /* 2 * Description:面向考试系统建立类TestSystem 3 * 4 * */ 5 6 package entity; 7 8 public class TestSystem { 9 10 private int num1; //声明两个操作数 11 private int num2; 12 private String oper

Linux基础入门(新版)(实验九-实验十二)

实验九 简单文本入门 一.常用的文本处理命令 二.文本处理命令 1.tr 命令 tr 命令可以用来删除一段文本信息中的某些文字.或者将其进行转换. 使用方式: tr [option]...SET1 [SET2]   常用的选项有: 选项 说明 -d 删除和set1匹配的字符,注意不是全词匹配也不是按字符顺序匹配 -s 去除set1指定的在输入文本中连续并重复的字符 操作举例: # 删除 "hello shiyanlou" 中所有的'o','l','h' $ echo 'hello sh

操作系统实验报告二

  操作系统实验报告二 姓名:许恺 学号:2014011329 日期:10月14日 题目1:编写线程池 关键代码如下: 1.Thread.h #pragma once #ifndef __THREAD_H #define __THREAD_H #include <vector> #include <string> #include <pthread.h> #pragma comment(lib,"x86/pthreadVC2.lib") using

【黑金原创教程】【FPGA那些事儿-驱动篇I 】实验十二:串口模块① — 发送

实验十二:串口模块① — 发送 串口固然是典型的实验,想必许多同学已经作烂,不过笔者还要循例介绍一下.我们知道串口有发送与接收之分,实验十二的实验目的就是实现串口发送,然而不同的是 ... 笔者会用另一种思路去实现串口发送. 图12.1 PS/2发送时序与串口发送时序. 如图12.1所示,串口发送时序相较PS/2发送时序,串口发送时序就像断了翅膀的小鸟般,没有时钟信号控制整个传输协议.除此之外,串口发送时序与PS/2发送时序近似的地方也非常惊人 ... 默认下,一帧PS/2数据有11位,对此一帧

18.06.26 16年程设期末10:游览规划

描述 一年一度的暴雪嘉年华(BlizzCon’16)即将盛大开幕,作为贪玩的助教小J,自然翘掉了程设期末前往参加.本届嘉年华为期m天,在这24*m小时的时间里,观众买券入场后方可体验各种免费及付费的游戏项目.参加本届嘉年华,首先需要在现场购买入场券,现场可以购买的入场券有三种,允许叠加购买使用: 单日券:售价100美金,购买后可以进入会场游玩24小时: 双日券:售价150美金,购买后可以进入会场游玩48小时: 三日券:售价200美金,购买后可以进入会场游玩72小时. 买券进入会场后,就可以在规定

项目二. 网络安全传输系统

项目二. 网络安全传输系统 sprint0-产品规划与设计 第1课-产品功能展示与模型设计 1. 功能 在底层开发上,先进行驱动开发,再往后发展就是对应的系统开发.要成为系统开发的工程师不了解应用编程的话也是行不通的. 本项目的服务器运行在pc的虚拟机上,客户端则安排在开发板上.我们在虚拟机上可以运行客户端,接下来我们在开发板上进行登录.可以选择的选项有: update Files Download Files Exit 也就是客户端可以将文件进行上传和下载服务器上的内容. 2. 模型 服务器: