1.实验要求
实验一:字符串解析实验
要求:
编写一个windows窗口程序,
输入:一个串x;
输出:点击按钮后输出
- x的所有前缀,x所有前缀的个数;
- x的所有后缀,x所有后缀的个数;
- x除前缀和后缀之外的所有子串,x除前缀和后缀之外的所有子串的个数。
2.程序运行
实现语言:C++,Qt
以下分别对字母串,数字串,中文串进行解析。
(1)解析英文串
(2)解析数字串
(3)解析中文串
3.项目构成
4.源代码
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QString>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString getqianzhui(QString S, QString * qianzhuiArray);//求S的前缀
QString gethouzhui(QString S, QString * houzhuiArray);//求S的后缀
//除去前后缀的所有字串,也就是S去头去尾的字符串的所有子串,并且去重;
QString getzichuan(QString S, QString * qianzhuisArray,QString * houzhuisArray,int & survivalNodecount);
private slots:
void on_btnsubmit_clicked();//当'提示'被点击
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
struct Node
{
bool _repeat;//判断是否与后面重复
QString _one;//某一个子串
Node * _next;//指向下一个Node节点
Node()
{
_repeat = false;
_one = "";
_next = nullptr;
}
Node(QString one)
{
_repeat = false;
_one = one;
_next = nullptr;
}
};
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnsubmit_clicked()
{
QString Yuans=ui->txtyuanstring->toPlainText();
//保存结果的string类型的数组
QString * qianzhuisArray = new QString[Yuans.size() + 1];//free了
QString *houzhuisArray = new QString[Yuans.size() + 1];//free了
QString qianzhuis="前缀"+QString::number(Yuans.size()+1)+"个:";
qianzhuis=qianzhuis+getqianzhui(Yuans,qianzhuisArray)+"\n";
QString houzhuis="后缀"+QString::number(Yuans.size()+1)+"个:";
houzhuis=houzhuis+gethouzhui(Yuans,houzhuisArray)+"\n";
//求子串除去前后缀,并且填充数组
QString zichuan="子串(除前后缀)";
if(Yuans.size()<=3)
{
zichuan=zichuan+"字符串长度不大于3,此项不存在";
}
else
{
int survivalNodecount=0;//因为无法确定去重后的子串有多少个,所以到函数里再进行赋值
QString finallyzichuan=getzichuan(Yuans,qianzhuisArray,houzhuisArray,survivalNodecount);
zichuan = zichuan+QString::number(survivalNodecount)+"个:"+finallyzichuan+"\n";//求S去头去尾后的后缀
}
QString Result=qianzhuis+houzhuis+zichuan;
ui->txtresultstring->setText(Result);
delete[] qianzhuisArray;
delete[] houzhuisArray;
}
QString MainWindow:: getqianzhui(QString S, QString * qianzhuiArray)//求s的前缀
{
int Size = S.size();
QString qianzhuis = "kong";//保存所有的前缀码
for (int turn = 1; turn <= Size; turn++)//得到所有前缀
{
QString turns = "";
//得出每一个前缀,j开头turn-1结束
for (int j = 0; j < turn; j++)
{
turns = turns + S[j];
}
qianzhuiArray[turn - 1] = turns;
qianzhuis = qianzhuis + " " + turns;
}
return qianzhuis;
}
QString MainWindow:: gethouzhui(QString S, QString * houzhuiArray)//求s的后缀
{
int Size = S.size();
QString houzhuis = "kong";//保存所有的前缀码
for (int turn = 1; turn <= Size; turn++)//得到所有前缀
{
QString turns = "";
//得出每一个前缀,j开头turn-1结束
for (int i = turn - 1; i < Size; i++)
{
turns = turns + S[i];
}
houzhuiArray[turn - 1] = turns;
houzhuis = houzhuis + " " + turns;
}
return houzhuis;
}
QString MainWindow:: getzichuan(QString S, QString *qianzhuisArray, QString *houzhuisArray, int &survivalNodecount)//求S除去前后缀后的所有子串
{
if (S.size() < 3)
return "字符串长度小于3,此类型不存在";
//下面都是原始字符串大于等于3的情况
Node *head = new Node();//头节点,利用链表的好处是不用计算子串的个数,而且方便去重,free了
Node *tail = head;
survivalNodecount = 0;//存活的节点,有效的节点,去链表重的时候也会用到
QString nowS = "";//去头去尾的S
QString nowzichuan = "";
for (int i = 1; i <= S.size() - 2; i++)
{
nowS = nowS + S[i];
}
for (int slength = 1; slength <= nowS.size(); slength++)//获取nowS所有长度的子串
{
//获取一种长度的子串
for (int start = 0; start <= nowS.size() - slength; start++)//定位头的范围,防止越界访问
{
QString one = "";//某长度的某一个子串
int end = start + slength - 1;//计算出尾巴的位置
for (int i = start; i <= end; i++)//根据头和尾截取字符串
{
one = one + nowS[i];
}
tail->_next = new Node(one);
tail = tail->_next;//tail指向尾巴节点
survivalNodecount++;//当前有效节点数增加1
}
}
//链表去重
//进行去重是因为abcba 就会得到b c b bc cb bcb其中有重复项
Node *p = head->_next;//为链表的每一个节点去重
while (p != nullptr)//为p指向的的节点去重
{
Node * find = p->_next;
while (find != nullptr)//找完为止
{
if (find->_one == p->_one)//找到重复的
{
p->_repeat = true;//说明被检测的节点p与后面的节点存在重复,标准P为重复节点
survivalNodecount--;//存活节点减少
break;//找到重复就跳出;
}
find = find->_next;
}
p = p->_next;
}
p = head->_next;//为链表的每一个节点去重,外部去重,去重前后缀
while (p != nullptr)//为p指向的的节点去重
{
for (int i = 0; i < S.size() + 1; i++)
{
if (qianzhuisArray[i] == p->_one || houzhuisArray[i] == p->_one)//找到重复的
{
if (p->_repeat == false)
{
p->_repeat = true;//说明被检测的节点p与后面的节点存在重复,标准P为重复节点
survivalNodecount--;//存活节点减少
}
break;//找到重复就跳出;
}
}
p = p->_next;
}
Node * q = head->_next;
//int i = 0;
while (q != nullptr)
{
if (q->_repeat == false)//输出的是没有被排除的survaval节点
{
nowzichuan = nowzichuan + q->_one + " ";
}
q = q->_next;
}
//释放链表
Node *m=head->_next;
while(m!=nullptr)
{
head->_next=m->_next;
delete m;
m=head->_next;
}
delete head;
return nowzichuan;//返回去重后的string
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}