代码很简单,写了一些注释;加上注释看就很清楚了。项目代码与报告的GitHub地址。
文件bloomfilter.cpp:
#include "bloomfilter.h"
// return a hash range from 0 to 79999
int hash(const char* str, int index)
{
int hash = 1;
int seed = 12345;
int curr;
switch(index)
{
case 0:
{
while(curr = int(*str++))
{
hash = 128 * hash + curr;
}
return abs(hash%80000);
}
case 1:
{
while(curr = int(*str++))
{
hash = (25536 * hash + curr)%80000;
}
return abs(hash);
}
case 2:
{
while(curr = int(*str++))
{
hash = (seed * hash + curr)%80000;
seed *= 123;
}
return abs(hash);
}
case 3:
{
while(curr = int(*str++))
{
hash += curr*curr;
}
return abs(hash%80000);
}
case 4:
{
while(curr = int(*str++))
{
hash += abs(curr*curr*curr);
}
return abs(hash%80000);
}
case 5:
{
while(curr = int(*str++))
{
hash *= (hash + curr*seed)%80000;
}
return abs(hash%80000);
}
case 6:
{
while(curr = int(*str++))
{
seed = 345;
hash = (seed * hash + curr)%80000;
seed *= 345;
}
return abs(hash);
}
}
return -1;
}
void initBitMap(unsigned char* bitMap)
{
for(int i = 0; i<10000;i++)
{
bitMap[i] = 0;
}
}
bool isKeyExistInBitMap(unsigned char* bitMap, const char* str)
{
for(int i = 0; i<7; i++)
{
int code = hash(str, i);
if(!((bitMap[code/8] >> code%8) % 2))
{
return false;
}
}
return true;
}
void appendKey2BitMap(unsigned char* bitMap, const char* str)
{
if(isKeyExistInBitMap(bitMap, str))
{
return;
}
for(int i = 0; i<7; i++)
{
int code = hash(str, i);
if(!((bitMap[code/8] >> code%8) % 2))
{
bitMap[code/8] += 1 << code%8;
}
}
}
文件bloomfilter.h:
#ifndef BLOOMFILTER_H
#define BLOOMFILTER_H
#include <stdio.h>
#include <math.h>
int hash(const char* str, int index);
void initBitMap(unsigned char* bitMap);
bool isKeyExistInBitMap(unsigned char* bitMap, const char* str);
void appendKey2BitMap(unsigned char* bitMap, const char* str);
#endif // BLOOMFILTER_H
文件main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
/*w.show();*/
QIcon icon("E:/code/Qt/build-TangTang-DFZ-Release/release/th.jpg");
w.setWindowIcon(icon);
w.setWindowTitle("Simple Code Editor");
w.show();
return a.exec();
}
文件mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSyntaxHighlighter>
#include <QPushButton>
#include <QObject>
#include <QTextEdit>
#include "myhighlight.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QFont font;
font.setFamily("Consolas");
font.setFixedPitch(true);
font.setPointSize(20);
editor = new QTextEdit;
editor->setFont(font);
highlighter = new myHighLight(editor->document());
setCentralWidget(editor);
setWindowTitle("Simple C++ Code Editor");
connect(ui->actionappend_key, &QAction::triggered, this, &MainWindow::appendKey);
connect(ui->actionDelete_key, &QAction::triggered, this, &MainWindow::deleteKey);
}
MainWindow::~MainWindow()
{
delete editor;
delete ui;
}
void MainWindow::appendKey()
{
QString selectedText = editor->textCursor().selectedText();
highlighter->appendKey(selectedText);
highlighter->setDocument(editor->document());
}
void MainWindow::deleteKey()
{
QString selectedText = editor->textCursor().selectedText();
highlighter->deleteKey(selectedText);
highlighter->setDocument(editor->document());
}
文件mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "myhighlight.h"
#include <QTextEdit>
#include <QtCore>
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
// append selected text for ui
void appendKey();
void deleteKey();
private:
Ui::MainWindow *ui;
QTextEdit *editor;
myHighLight *highlighter;
};
#endif // MAINWINDOW_H
文件mainwindow.ui自己拖一拖就行!
文件myhighlight.cpp:
#include "myhighlight.h"
#include "bloomfilter.cpp"
#include <QtGui>
myHighLight::myHighLight(QTextDocument *parent)
: QSyntaxHighlighter(parent)
{
// find each word
rule = new QRegExp("(\\b)(\\w+)(\\b)");
format.setForeground(Qt::blue);
format.setFontWeight(QFont::Bold);
initBitMap(bitMap);
QStringList keyWords = cppKeyword();
for(QString key : keyWords)
{
appendKey(key);
}
}
myHighLight::~myHighLight()
{
if(rule)
delete rule;
}
QStringList myHighLight::cppKeyword()
{
return QStringList()<<"asm"<<"auto"<<"bool"<<"break"<<"case"<<"catch"<<"char"
<<"class"<<"const"<<"const_cast"<<"continue"<<"default"<<"delete"
<<"do"<<"double"<<"dynamic_cast"<<"else"<<"enum"<<"explicit"
<<"export"<<"extern"<<"false"<<"float"<<"for"<<"friend"<<"goto"
<<"if"<<"inline"<<"int"<<"long"<<"mutable"<<"namespace"<<"new"
<<"operator"<<"private"<<"protected"<<"public"<<"register"
<<"reinterpret_cast"<<"return"<<"short"<<"signed"<<"sizeof"<<"static"
<<"static_cast"<<"struct"<<"switch"<<"template"<<"this"<<"throw"
<<"true"<<"try"<<"typedef"<<"typeid"<<"typename"<<"union"<<"unsigned"
<<"using"<<"virtual"<<"void"<<"volatile"<<"wchar_t"<<"while";
}
//QVector<int> myHighLight::Hash(QString word)
//{
// std::hash<std::string> str_hash;
// QVector<int> res;
// if(word.size()%hashCount == 0)
// {
// word += " ";
// }
// QString key;
// while(key.size() < 100)
// {
// key += word;
// }
// for(int i = 0; i<hashCount; i++)
// {
// QString key0;
// for(int j = i;j<key.size(); j+=hashCount)
// {
// key0.append(key[j]);
// }
// res.append(abs(int(str_hash(key0.toStdString()))%(BloomFilter.size()*8-1)));
// }
// return res;
//}
void myHighLight::appendKey(QString key)
{
if(!rule->exactMatch(key))
{
qDebug()<<"KeyWord "<<key<<" is not a word";
return;
}
if(whiteNameList.contains(key))
{
whiteNameList.removeOne(key);
}
appendKey2BitMap(bitMap, key.toStdString().data());
// if(isKeyExisted(key))
// {
// qDebug()<<"KeyWord "<<key<<" alredy existed!";
// return;
// }
// QVector<int> hash = Hash(key);
// for(auto code : hash)
// {
// if(!((BloomFilter[code/8] >> code%8) % 2))
// {
// BloomFilter[code/8] += 1 << code%8;
// }
// }
}
void myHighLight::deleteKey(QString key)
{
if(!rule->exactMatch(key))
{
qDebug()<<"KeyWord "<<key<<" is not a word";
return;
}
if(whiteNameList.contains(key))
{
qDebug()<<"KeyWord "<<key<<" to be deleted has already been in whitelist";
return;
}
if(!isKeyExisted(key))
{
qDebug()<<"KeyWord "<<key<<" to be deleted is not in the BloomFilter!";
return;
}
whiteNameList.push_back(key);
qDebug()<<whiteNameList;
}
bool myHighLight::isKeyExisted(QString key)
{
if(whiteNameList.contains(key))
{
return false;
}
return isKeyExistInBitMap(bitMap, key.toStdString().data());
// QVector<int> hash = Hash(key);
// for(auto code : hash)
// {
// if(!((BloomFilter[code/8] >> code%8) % 2))
// {
// return false;
// }
// }
// return true;
}
void myHighLight::highlightBlock(const QString &text)
{
int index = rule->indexIn(text);
while(index >= 0)
{
int length = rule->matchedLength();
if(isKeyExisted(text.mid(index, length)))
{
setFormat(index, length, format);
}
index = rule->indexIn(text, index + length);
}
}
文件myhighlight.h:
#ifndef MYHIGHLIGHT_H
#define MYHIGHLIGHT_H
#include <QSyntaxHighlighter>
#include <QTextCharFormat>
class QTextDocument;
class myHighLight : public QSyntaxHighlighter
{
Q_OBJECT
public:
myHighLight(QTextDocument *parent = 0);
~myHighLight();
static QStringList cppKeyword();
// get a Hash Value Array from a word
QVector<int> Hash(QString word);
// append a keyword to the bloom filter
void appendKey(QString key);
// delete a keyword from the bloom filter
void deleteKey(QString key);
// judge if the word is existing in the bloom filter
bool isKeyExisted(QString key);
protected:
// highlight the keyword block on updating document
void highlightBlock(const QString &text);
private:
// regression expression for searching every words
QRegExp* rule;
// the format we plan to apply in keyword
QTextCharFormat format;
// the structure to store keywords. it is expected to store 8000 words in total.
// More details in program report.
unsigned char bitMap[10000];
// QVector<unsigned char> BloomFilter;
// each keyword in the whitelist is considered not to be in the BloomFilter
QVector<QString> whiteNameList;
// // the hash function count. 7 is best for 1% error possibility
// const int hashCount = 7;
};
#endif // MYHIGHLIGHT_H