QT容器很香之QList<T>实战举例

本文介绍了QT中的QList<T>容器类,它提供基于索引的快速访问和插入删除。QList<T>是泛型容器,允许存储特定类型的对象,如QList<float>和QList<int>。通过实例展示了如何使用QList接收和处理设备计算数据,利用FIFO(先进先出)机制进行数据处理。使用QList可以简化编程,提高效率。
摘要由CSDN通过智能技术生成

[导读] 大家好,我是逸珺。

今天来聊一下QList,QList 是一种QT容器,如果能熟练使用它,会非常香。

什么是QList<T>

QList<T> 是QT中通用容器类,它将对象存储在一个表中,该表提供基于索引的快速访问和基于索引的插入和删除。熟悉C++标准库的话,就类似于std:list<T> ,为什么这里描述是跟了一个<T>呢?因为是容器类,所谓容器,就把它想象成一个能装东西的框,但是这与现实生活中的框还是有区别的,现实中的框可以随便往里面装东西,先装几个土豆,再放两颗白菜,再放一本书....,随便装,只要放的下。

但是,这个容器类跟的这个<T>,是指泛型,从字面意思上看,好像也是什么对象都可以往里面放,但是这么几层需要理解:

  • 对于特定的容器,需要指明其可装进去的对象类型

  • 对于特定的容器,只能装指定的类型

那么,为什么又说是泛型呢?就是说不同的QList对象,根据所指定的T的类型,可以装各自不同类型的对象,比如:

QList<float> m_list1;
QList<int>  m_list2;

m_list1可以存float型的对象,而m_list2则可以装int型对象。这是怎么做到的呢,是C++编译器在编译期根据T本身类型编译绑定的。

前面说QList是基于索引插入和删除的容器类,何以见得呢?来看看QT官方文档例子:

QList<QString> list = { "one", "two", "three" };

这意味着这三个元素是这样放的:

实战例子

假设有这么一个需求,利用一个socket接收一个设备的计算数据,每一个计算数据是这样的:

typedef struct _t_measure {
  qint64 addr;
  qint64 Real;
  qint64 Imag;
  qint64 rms;
}t_measure;

在类中加入QList<T>,这里T是t_measure:

QList<t_measure> m_measure;

一个报文里面有多个测量结果,QT写的应用程序,需要一边收一边显示或者存储,接收可能是一个线程,或者sokect消息回调函数,比如是UDP接收的:

connect(m_MeasureUdpSocket, SIGNAL(readyRead()),
        this, SLOT(readMeasurement()));

接收函数:

#define MAX_BUF_SIZE        (300)
#define MAX_BUF_SIZE_BYTES  (MAX_BUF_SIZE*8)
void Measurement::readMeasurement()
{
  typedef union _u_buf {
    char  buf[MAX_BUF_SIZE_BYTES];
    qint64 dpts[MAX_BUF_SIZE];
  }u_buf;

  u_buf buffer;
  t_measure *pRaw=nullptr;
  int len = 0;
  while (m_MeasureUdpSocket->hasPendingDatagrams()) {
    len = m_MeasureUdpSocket->pendingDatagramSize();
    if(len>MAX_BUF_SIZE_BYTES)
       len = MAX_BUF_SIZE_BYTES;
      
    m_MeasureUdpSocket->readDatagram(buffer.buf, len);
    if(buffer.dpts[0]==0x7FAAAAF7CCCCCCCC) {
      pRaw = (t_measure *)&buffer.dpts[2];
      for(int i=0;i<buffer.dpts[1];i++) {
         m_measure.append(*pRaw);
         pRaw++;
      }
    }
  }
}

假设定义一个头部标识为0x7FAAAAF7CCCCCCCC, 头部正确,然后按照长度不断将接收到的数据追加到表的尾部。

在另一个地方可以从头部不断取出数据进行后续处理,比如进行进一步计算,显示或存储,比如:

  if(m_measure.isEmpty()) {
    return;
  }

  int pts = m_measure.size();
  t_measure temp;
  for(int i=0;i<pts;i++) {
    temp = m_measure.takeFirst();
    
    //做后续处理
    ......
  }

上述例子,用一个示意图描述,大概就是下面这样:

接收端不断在尾部追加,而处理端则在头部取出,就是一个FIFO操作。

如果不使用QList<T>,自己实现一个FIFO则需要考虑很多细节问题,所以使用C++,或者QT要尽量摆脱C语言的编程习惯,尽量使用已有的轮子,这会大大提高生产效率。

总结一下

使用C++,熟悉掌握容器这些泛型编程方法,不用自己去管理这些底层实现,会大大提高效率。我觉得蛮香,你觉得呢?

—— The End ——

推荐阅读  点击蓝色字体即可跳转

 使用FreeRTOS要好好理解任务状态机?

☞ 手把手教你在STM32F4上跑freeRTOS

☞ 图解FreeRTOS原理系列之任务管理器基本框架

☞ 傅里叶变换、拉普拉斯变换、Z 变换的联系是什么?为什么要变换

欢迎转发、留言、点赞、分享给您的朋友,感谢您的支持!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式客栈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值