bitset 和map的使用案例
需求描述
在界面中增加一个combobox,记录添加的标记值,标记值是一个有序的序列(MR,M1,M2,M3,M4),能进行添加,删除,和清空combobox中的任意值。在添加的时候一定按照序列,比如当存在MR M1 M2 M3时,先删除了M2,此时的序列为MR M1 M3,点击添加此时应该添加M2 再点击添加就是添加M4。
技术支持
bitset 用于做序列标记,这个地方可以使用array,但bitset最大的优势在于节约空间。
std::bitset<8> marker_bitset_;
map 使用map的主要作用是为了实现,枚举类型和字符串的一一对应关系。
std::map<marker_type_t, QString> marker_2_name_;
思路分析
定义一个枚举用于,记录每种标记的类型
enum class marker_type_t {
MR = 0,M1,M2,M3,M4
};
定义两个map,来显示字符串和枚举类型的相互查找,这个地方也可以使用一个map,然后用过遍历的方式来进行字符匹配。利用second 和first方法。但是为了代码逻辑的清晰,我选择了两个map的方式:
void makerdata_update_t::initMarkers() {
marker_2_name_[marker_type_t::MR] = u8"MR";
marker_2_name_[marker_type_t::M1] = u8"M1";
marker_2_name_[marker_type_t::M2] = u8"M2";
marker_2_name_[marker_type_t::M3] = u8"M3";
marker_2_name_[marker_type_t::M4] = u8"M4";
for (const auto& [k, v] : marker_2_name_)
name_2_marker_[v] = k;
}
//方法1
void makerdata_update_t::changeActiveMarker(QString markername) {
active_marker_ = name_2_marker_[markername];
}
//方法2
void makerdata_update_t::changeActiveMaker(QString makername) {
for (auto it = marker_2_name_.begin(); it != marker_2_name_.end(); ++it) {
if (!it->second.compare(makername.toUtf8()))
{
active_maker_ = it->first;
break;
}
}
}
技术拓展
做完以后发现,在和同事沟通的时候发现c++ boost库中有“多索引”的方法。再以后的学习中,我会将这部分的代码补上。现在还没有学习到这里。
效果截图
在QML中的界面效果,点击“+”就是添加一个标记,点击“-”就是去掉当前combobox中选中的标记值,“清空”即删除所有的标记值。
代码附录
核心代码实现的c++类,关于QML的属性绑定,不是这次blog的关键。相关源码就不用附加上了,因为里面有很多相关的东西,不好做代码的分离。
//markerupdate.hpp
enum class marker_type_t {
MR = 0,
M1,
M2,
M3,
M4
};
struct makerdata_update_t :public QObject {
Q_OBJECT
std::map<marker_type_t, QString> marker_2_name_;
std::map<QString, marker_type_t> name_2_marker_;
std::bitset<8> marker_bitset_;
Q_PROPERTY(int markerCount READ markerCount NOTIFY markerCountChanged);
Q_PROPERTY(QStringList markersList READ markersList NOTIFY markerCountChanged);
Q_PROPERTY(int activeMarker READ activeMarker NOTIFY markerCountChanged);
public:
makerdata_update_t(data_t&, rtsa_handle_t& rtsa);
void initMarkers();
int insertMarker();
void deleteMarker();
void clearMarker();
QStringList markersList() {
return getMarkersList();
}
int activeMarker() {
return (int)active_marker_;
}
int markerCount() {
return getMarkersCount();
}
void setIsLoadData(bool val) {
is_load_data_ = val;
}
public:
Q_INVOKABLE QStringList getMarkersList();
Q_INVOKABLE void changeActiveMarker(QString);
Q_INVOKABLE int getMarkersCount();
Q_INVOKABLE void markerAdd();
Q_INVOKABLE void markerDelete();
Q_INVOKABLE void markerPeak();
Q_INVOKABLE void markerClear();
};
//markerupdate.cpp
makerdata_update_t::makerdata_update_t(data_t& data, rtsa_handle_t& rtsa){
initMarkers();
}
void makerdata_update_t::initMarkers() {
marker_2_name_[marker_type_t::MR] = u8"MR";
marker_2_name_[marker_type_t::M1] = u8"M1";
marker_2_name_[marker_type_t::M2] = u8"M2";
marker_2_name_[marker_type_t::M3] = u8"M3";
marker_2_name_[marker_type_t::M4] = u8"M4";
for (const auto& [k, v] : marker_2_name_)
name_2_marker_[v] = k;
}
QStringList makerdata_update_t::getMarkersList() {
QStringList marker_list;
for (std::size_t i = 0; i < marker_bitset_.size(); ++i) {
if (marker_bitset_[i])
{
marker_list.append(marker_2_name_[marker_type_t(i)]);
}
}
if (marker_list.count() == 0)
marker_list.append(u8"无");
return marker_list;
}
void makerdata_update_t::changeActiveMarker(QString markername) {
active_marker_ = name_2_marker_[markername];
}
int makerdata_update_t::insertMarker() {
for (std::size_t i = 0; i < (std::uint32_t)marker_type_t::M4 + 1; ++i) {
if (!marker_bitset_[i])
{
marker_bitset_.set(i);
active_marker_ = marker_type_t(i);
break;
}
}
emit markerCountChanged();
return (int)marker_bitset_.count();
}
void makerdata_update_t::deleteMarker() {
if (active_marker_ == marker_type_t::MR)
{
for (std::size_t i = (std::uint32_t)marker_type_t::M4 ; i >= 0; --i) {
if (marker_bitset_[i])
{
marker_bitset_.reset(i);
active_marker_ = marker_type_t(i);
break;
}
}
}else
marker_bitset_.reset((std::uint32_t)active_marker_);
emit markerCountChanged();
}
void makerdata_update_t::clearMarker() {
for (std::size_t i = 0; i < (std::uint32_t)marker_type_t::M4 + 1; ++i) {
marker_bitset_.reset(i);
emit markerCountChanged();
}
}
int makerdata_update_t::getMarkersCount() {
return (int)marker_bitset_.count();
}
void makerdata_update_t::markerAdd() {
insertMarker();
}
void makerdata_update_t::markerDelete() {
deleteMarker();
}
void makerdata_update_t::markerClear() {
clearMarker();
}