2.4 算法及正则表达式

一.Qt中的算法及正则表达式

1.1 Qt中的常用的算法(使用到了QtAlgorithms类里面的几个函数)

  1.1.1 简单了的几个算法函数

  与之相关的头文件就是QtAlgorithms,里面有几个函数就简单介绍一下(仍然是创建一个Qt控制台项目)

  const T&QtAlgorithms::qAbs(T&a);//返回某个变量的绝对值

  const T&QtAlgorithms::qMax(T&a,T&b);//返回两个数最大的一个

  int QtAlgorithms::qRound(double&d);//以四舍五入的方式返回该浮点数最接近的整数(规则是四舍五入)

  void QtAlgorithms::qSwap(T&a,T&b);//交换两个对象(不仅仅支持基本数据类型,还支持自定义数据类型和Qt内置的一些类类型)

///Qt中一些基本的算法函数
    double a = -19.3;
    double b = 9.7;
    double c = qAbs(a);//qAbs函数返回绝对值(同样是一个函数模板)
    double max_value = qMax(a,c);//qMax函数(这是一个模板函数)返回两个数之间的最大值
    int bn = qRound(b);//qRound函数,通过四舍五入返回一个浮点数与之最近的整数(10)
    int cn = qRound(max_value);//19
    qDebug()<<"bn="<<bn<<",cn="<<cn;//10,19
    qSwap(bn,cn);//交换两个数据的值
    qDebug()<<"bn="<<bn<<",cn="<<cn;//19,10

  1.1.2 其他的一些算法函数(实际上Qt的这些算法函数都和C++的STL容器里面的算法函数很类似,无非就是在前面多加了一个q前缀)

    1.1.2.1 qFill函数

///1.qFill函数(用于填充某个容器或者是填充容器某一段迭代器范围内的数据)
    QList<int>q_list;
    qFill(q_list,120);//QFill用来使用特定的数来填充容器(当然你也可以指定范围[使用迭代器])
    for(auto elem:q_list)
    {
        qDebug()<<elem;
    }
    //如果想只填充容器中某一段范围的数据
    QMap<QString,QString>map;
    //比如我先往map容器中插入10个元素
    for(int i = 0;i<10;++i)
    {
        map[QString("Key%1").arg(i)] = QString("Value%1").arg(i);
    }
    //然后我遍历一下这个容器
    for(QMap<QString,QString>::iterator it = map.begin();it!=map.end();it++)
    {
        qDebug()<<it.key()<<":" << it.value();
    }
    //然后我试图将从Key3~Key5范围内的所有的值修改为"蜡笔小新Pointer"
    QMap<QString,QString>::iterator start = map.begin()+3;
    QMap<QString,QString>::iterator end = start+3;//由于不包括end的位置,因此必须加1
    qFill(start,end,QString("蜡笔小新Pointer"));
    for(QMap<QString,QString>::iterator it = map.begin();it!=map.end();it++)
    {
        qDebug()<<it.key()<<":" << it.value();
    }
    //注意:对于qFill的使用,不能使用只读迭代器去操作它(因为qFill会对容器进行读写操作)

   1.1.2.2 qCopy函数

/// qCopy函数用于复制某个输入迭代器的开始位置到该输入迭代器的结束位置的一段数据,将其
    /// 中的这段数据复制到新的容器的迭代器的指定的位置上(他会覆盖掉后面的数据哦)
    QVector<QString>str_vector;
    str_vector.append("AAA");
    str_vector.append("BBB");
    str_vector.append("CCC");
    str_vector.append("DDD");
    str_vector.append("EEE");
    //然后我们再定义一个vector,但是我们得为其预先分配大小(如果不分配,则会出现内存错误)
    QVector<QString>des_vector(10);//默认都是""字符串
    //我们想把str_vector的从下标1到下标3位置的元素拷贝到string_list的下标2开始的位置之后(会覆盖原来的数据)
    QVector<QString>::iterator start_copy = str_vector.begin()+1;
    QVector<QString>::iterator end_copy = str_vector.begin()+4;
    qCopy(start_copy,end_copy,des_vector.begin()+2);
    for(auto elem:des_vector)
    {
        qDebug()<<elem;
    }
    ///3.qCount函数
    /// qCount函数用于计数,也就是计算某个容器中有多少个值是该传入的参数的值,通过一个引用存储所计算的数
    QStringList some_strs;
    some_strs<<"A"<<"A"<<"B"<<"C"<<"A"<<"B"<<"D"<<"E"<<"F";//我们往这个StringList里面加入一些的字符串
    QMap<QString,int>cnt_obj;//用于存储某个字符串有多少个的这样子的键值对关系
    for(auto elem:some_strs)//遍历some_strs里面有哪些字符串
    {
        int elem_cnt;//定义一个有多少个存储字符串元素数量的变量
        qCount(some_strs,elem,elem_cnt);//对该字符串进行计数
        cnt_obj.insert(elem,elem_cnt);//将结果插入到计数对象中
    }
    QMapIterator<QString,int>cnt_obj_iter(cnt_obj);//这里我们使用Java风格迭代器
    while (cnt_obj_iter.hasNext())
    {
        cnt_obj_iter.next();//必须要先next一下(因为刚开始迭代器指针指在第一个元素的前面)
        qDebug()<<"字符串"<<cnt_obj_iter.key()<<"一共有:"<<cnt_obj_iter.value()<<"个";
    }

    1.1.2.3 qEqual函数

/// 该函数是用来比较每某一个容器的某一迭代器范围内的值是否和另一个迭代器的某个迭代位置的值是否相等
    QLinkedList<QString>str_linkList;
    str_linkList<<"Hello"<<"Hello"<<"Hello"<<"hEllo";//我往这个容器中插入4个字符串元素
    QStringList str_stringlist;
    str_stringlist<<"Hello"<<"Hello"<<"Hello"<<"hEllo";
    ///然后我来比较在str_linkList中的下标0到下标2(不包括2的位置)的元素范围是否都和str_stringlist中begin位置
    /// 一直到最后一个的元素值一一对应是否相同
    qDebug()<<qEqual(str_linkList.begin(),str_linkList.begin()+3,str_stringlist.begin());
    //如果我修改了其中的一个
    str_stringlist[2] = "AWD";
    qDebug()<<qEqual(str_linkList.begin(),str_linkList.begin()+3,str_stringlist.begin());
    ///这个函数实际上比较的第一个容器的迭代器[start,end)和第二个容器的[start,...)是否相同,要都相同才
    /// 返回true

    1.1.2.4 qFind函数

///该函数有两种重载形式
    ////5.1 通过直接传入容器及腰查找的值返回该值所在的该容器的只读迭代器的位置
    ///这里我们先使用一个链表来做这个测试
    QLinkedList<QString>str_lst = {QString("Hello"),QString("World!"),QString("BoBo"),QString("呵呵")};
    QLinkedList<QString>::const_iterator str_lstIter = qFind(str_lst,"Hello");
    qDebug()<<*str_lstIter;//我们可以输出这个位置的具体元素(但不能对该元素进行写操作)
    ////5.2 通过指定对某一个容器的一段迭代范围来查找某个值并返回该值所在的迭代器的位置(这个是可读写的)
    QLinkedList<QString>::iterator str_list_start = str_lst.begin()+1;
    QLinkedList<QString>::iterator str_list_end = str_lst.begin()+2;
    QLinkedList<QString>::iterator it = qFind(str_list_start,str_list_end,"World!");
    qDebug()<<*it;

  1.1.2.5 qSort函数

class Student
{
    friend bool lessThanStudents(Student&stus_1,Student&stus_2);
public:
    Student(const QString _name,double _score)
    {
        this->s_name = _name;
        this->s_score = _score;
    }
    Student(const Student&stu_obj)
    {
        this->s_name = stu_obj.s_name;
        this->s_score = stu_obj.s_score;
    }
    ~Student()
    {

    }
public:
    void ShowStudent()
    {
        qDebug()<<"姓名:"<<s_name<<",分数:"<<s_score;
    }
private:
    double s_score;
    QString s_name;
};
bool lessThanStudents(Student&stus_1,Student&stus_2)
{
    return stus_1.s_score>stus_2.s_score;
}
/// 该函数的作用是对某个容器进行排序[默认为升序排列](即可以直接传入容器,还可以传入迭代器的位置)
    QList<int>some_interger = {11,9,4,6,5,3,2,7,9,11,12};
    qSort(some_interger);
    for(auto elem:some_interger)
    {
        qDebug()<<elem;
    }
    ///那假如我想对自定义数据类型排序呢?
    /// 对于自定义数据类型排序,我们第一步需要自定义一个类型
    /// 然后由于会使用到容器,因此我们必须手动实现我们这个类的拷贝构造函数
    /// 直接对两个类对象比较,qSort是不知道应该按Student什么去比较的,因此我们需要写一个叫做谓词的东西
    /// 这个谓词实际上就是一个全局函数,这个函数只能有两个参数,一个是第一个要比较的对象,然后是
    /// 第二个比较的对象,然后这个谓词函数必须返回bool类型,比如我们这里对Student类排序实际上本质排序的
    /// 就是学生的分数,另外我们这个全局的谓词函数用到了Student类的私有成员,因此这个谓词函数必须是Student
    /// 的友元函数
    QList<Student>some_stus = {Student("王帅",55.3),Student("郭丰",57.2),Student("李森",43.5),Student("蜡笔小新Pointer",21.4)};
    QList<Student>::iterator stus_iter_start = some_stus.begin();//容器的开始位置
    QList<Student>::iterator stus_iter_end = some_stus.end();//容器的结束位置
    qSort(stus_iter_start,stus_iter_end,lessThanStudents);
    for(auto stu:some_stus)
    {
        stu.ShowStudent();
    }

 1.2 Qt中的正则表达式

  众所周知,正则表达式是用来匹配一定规则的字符串的,实际上正则表达式在很多的场景有着广泛的用途,比如电话号码的匹配归属地;用户在设置密码时,可以规定用户设置的密码必须按照一定的规则来进行设置;又比如还可以通过正则表达式来查找一个很大的文本文件中的一些满足某种规律的字符串等,实际上Qt中也有正则表达式

  Qt的正则表达式也有对应的类来负责操作正则表达式,它的名字叫QRegExp

  1.2.1 QRegExp类可以对字符串进行有效性检测,查找,替换以及字符串的分割

  1.2.2 在了解QRegExp之前,我们需要简单说一下正则表达式中常用的通配符和一些元字符

    1.2.2.1 通配符.表示匹配一个任意的字符

    1.2.2.2 通配符^用于匹配字符串的开始位置

    1.2.2.3 通配符$用于匹配字符串的结束位置

    1.2.2.4 []表示匹配一个位于[]里面的任意一个字符

    1.2.2.5 通配符*表示匹配任意多个任意的字符(至少有一个)

    1.2.2.6 通配符+表示匹配至少一个或多个字符(必须至少是1个)    

    1.2.2.7 通配符?表示只匹配一个或没有的任意一个字符

  1.2.3 元字符

    \d 表示所有的数字(0123456789)

    \D 表示不是所有的数字

    \w 表示匹配所有的数字字母下划线

    \s 匹配空白字符

    \S 匹配所有的非空白字符

    ^ 表示匹配不是这个字符的其他的字符,比如[abc]表示匹配a,b,c中的一个,[^abc]表示匹配不是a,不是b,也不是c 

  1.2.4 量词

    量词表示将某个元字符匹配多少次

    E? 表示将某一个字符只匹配0次或1次

    E+ 表示至少匹配1次或多次

    E* 表示匹配0次或多次

    E[n] 表示匹配n次

    E[n,] 至少匹配n次

    E[,m] 最多匹配m次

    E[n,m] 表示至少匹配n次,至多匹配m次

  

posted @ 2023-07-10 22:37  蜡笔小新Pointer  阅读(106)  评论(0)    收藏  举报