C++抽象编程——STL(5)——set集合的基本输入输出

本文详细介绍了C++标准库中的set类,包括其基本操作、常用方法及如何使用set类来实现字符处理功能。通过具体实例展示了如何创建、查询、更新集合,并提供了使用set类进行字符类型判断的应用案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

the Set class

还有一个最有用的集合类,就是set(集合)类了,出口的方法如下图,这个类我们用来模拟数学上的集合,也就是说这个类里的元素是无序且其值只出现一次。set类在许多算法应用中是极其有用的。所以我们应该从一些实例中去体验和感受它们是怎么工作以及为什么在程序中如此有用。
先介绍一下set的常见的方法:

在这里我们再也不是用我们熟悉的pop跟push(push_back)函数来放入或者是取出元素了,我们用insert跟erase函数来进行一些的添加跟删除。
我们了解一下我们的常用方法吧:

方法用法
插入删除
insert(value)向集合中插入一个元素
erase()擦除元素中的一个或者一段元素
clear()清除集合中的元素
查找
find()查找value的值,返回下标位置,否则,返回最后一个元素后面一个位置(即迭代器的end)
容量
empty()判断集合是否为空
size()返回集合中的元素个数
max_size()返回集合的最大容量
迭代器
begin()返回开头的迭代器
end()返回结尾的迭代器
rbegin()反向遍历的首个位置迭代器
rend()反向遍历的最后位置的迭代器

关于迭代器的介绍,看这个:C++抽象编程——STL(4)——vector类

Implementing the library

我们先来试试这些集合可以干什么吧,我们之前提过一个功能很强大的字符处理头文件,(详情见: C++抽象编程——字符串(3)——< cctype >库在字符串中的应用)想知道它是怎么实现的吗?具体的细节我们就不必要理解了,那么我们要做的是了解它是怎么样的一个思路吧。
我们可以举个例子,比如我们有个判断是不是数字的方法
isdigit(ch)
实现起来很简单:

bool isdigit(ch) {
return ch >= '0' && ch <= '9';
}

但是用户往往输入的是一串的数字,所以我们可以建立一个集合,里面的元素为{0,1,2,3,4,5,6,7,8,9},我们可以检测ch在不在这个集合里面。那么我们沿着这个思路写出大概的代码:

#include <iostream>
#include <set>
#include <cctype>
using namespace std;
/*将字符串变为集合*/ 
set<char> setFromString(string str);
/*函数声明*/
bool isFind(char ch, set<char> DIGIT_SET);
bool isFind(char ch, set<char> LOWER_SET);
bool isFind(char ch, set<char> UPPER_SET);
bool isFind(char ch, set<char> PUNCT_SET);
bool isFind(char ch, set<char> SPACE_SET);
bool isFind(char ch, set<char> XDIGIT_SET);
/*定义集合*/ 
set<char> DIGIT_SET = setFromString("0123456789");
set<char> LOWER_SET = setFromString("abcdefghijklmnopqrstuvwxyz");
set<char> UPPER_SET = setFromString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
set<char> PUNCT_SET = setFromString("!\"#$%&'()*+,-./:;<=>?@[\\]^_‘{|}");
set<char> SPACE_SET = setFromString(" \t\v\f\n\r");
set<char> XDIGIT_SET = setFromString("0123456789ABCDEFabcdef");
/*定义函数*/ 
bool isdigit(char ch) { return isFind(ch, DIGIT_SET); }
bool islower(char ch) { return isFind(ch, LOWER_SET); }
bool ispunct(char ch) { return isFind(ch, PUNCT_SET); }
bool isspace(char ch) { return isFind(ch, SPACE_SET); }
bool isupper(char ch) { return isFind(ch, UPPER_SET); }
bool isxdigit(char ch) { return isFind(ch, XDIGIT_SET); } 

set<char> setFromString(string str) {
    set<char> set;
    for (int i = 0; i < str.length(); i++) {
    set.insert(str[i]);
    }
    return set;
}
/*判断集合中是否存在该元素*/
bool isFind(char ch, set<char> DIGIT_SET) {
    set<char>::iterator it;
    it = DIGIT_SET.find(ch);
    if(it != DIGIT_SET.end()) return true;
    else return false;

}
......

在这里我们注意,这个文件我没有写main函数,所以是不能运行的。你可以自己添加main函数去试试这些功能。这里的最后我用省略号省略了一系列的isFind函数,因为后面的函数只是最后的参数的名字改一下就可以了。最后我觉得set< char > setFromString(string str) 这个方法很好,我们可以参考这个改一下类型,比如vector类,我们就可以简化输入。
再认真看看最后的isFind函数,这里有一行代码:

set<char>::iterator it;
    it = DIGIT_SET.find(ch);

iterator是一个迭代器,::为域运算符,所以就是说迭代器it是set< char >类型的迭代器,因为我们前面的DIGIT_SET.find()函数返回的是迭代器,不是一个数值。

set集合的输入与输出

我们还可以再举例一个输入输出的简单例子:
第一,先参考vector,试试输出

先看看错误提示,no match for “operator[]”…,翻译过来就是没有匹配的[ ]运算符,那么常规方法不行,我们就试试它提供的迭代器来完成

#include <iostream>
#include <set>
using namespace std;
int main(){
    set<int> s;
    set<int>::iterator it;
    for(int i = 0; i <= 9; i++){
        s.insert(i);
    }
    for(it = s.begin(); it != s.end(); it++) 
    cout << (*it) << " ";

    /* it = s.find(5);    /*查找键值为5的元素*
    if(it != s.end()){    /*当it不为尾部的迭代器的时候,就找到了 
    cout << *it <<endl;
    }else{
    cout<<"不存在这个元素"; 
    }*/
    return 0;

}

输出的结果如图:

这里我有一个地方注释掉了,这里面就是find方法的运用,我就不上图了,有兴趣就取消注释来运行看看吧。接下来就介绍set的用途吧

<think>我们正在讨论的是如何在QML中读取QVariantMap中存储的char类型的值。在C++中,char类型是一个8位整数,但在QML中,当我们从QVariantMap中读取时,可能会遇到类型转换的问题。 在C++中,如果我们将一个char值放入QVariantMap,它会被转换为QVariant。QVariant对于char类型,实际上会将其视为一个整数(因为char本质上是整数类型)。当这个QVariantMap被传递到QML时,QML引擎会将整数转换为JavaScript的Number类型(即双精度浮点数)。因此,在QML中,我们得到的是一个数字。 但是,如果我们想要将这个数字转换回一个字符(即对应的ASCII字符),我们可以使用JavaScript的String.fromCharCode()函数。 ### 步骤 1. **在C++中存储char值到QVariantMap**: 在C++代码中,我们将char值作为整数存储到QVariantMap中。例如: ```cpp QVariantMap data; char myChar = 'A'; data["charValue"] = QVariant(static_cast<int>(myChar)); // 显式转换为int // 或者直接存为int,因为char会自动提升为int // data["charValue"] = myChar; // 这样也可以,因为QVariant支持int ``` 2. **在QML中读取并转换**: 在QML中,我们读取到的是一个整数,然后使用`String.fromCharCode`将其转换为字符: ```qml Text { text: "The character is: " + String.fromCharCode(dataMap.charValue) } ``` ### 示例 假设我们有一个C++对象将QVariantMap暴露给QML: **C++端**: ```cpp // 假设在某个类中 QVariantMap createData() { QVariantMap map; map["charKey"] = 'B'; // 这里会自动转换为int,然后存储为QVariant(int) return map; } // 将map暴露给QML,例如通过上下文属性 engine.rootContext()->setContextProperty("myData", createData()); ``` **QML端**: ```qml import QtQuick 2.15 Item { Component.onCompleted: { // 读取整数并转换为字符 var charValue = myData.charKey; // 这是一个数字 console.log("As number:", charValue); // 输出66(如果存储的是'B') console.log("As character:", String.fromCharCode(charValue)); // 输出'B' } Text { text: "Character: " + String.fromCharCode(myData.charKey) } } ``` ### 注意事项 - **直接存储char**:如果我们直接存储char(如`map["key"] = 'A'`),QVariant会将其存储为int。在QML中读取时,我们得到的是整数(ASCII码)。 - **如果存储为字符串**:如果我们希望直接得到字符串(比如一个字符的字符串),那么可以在C++端将其转换为QString再存储: ```cpp map["charAsString"] = QString(QChar(myChar)); // 或者 QString(1, myChar) ``` 这样在QML中就可以直接作为字符串使用了。 - **非ASCII字符**:如果char是扩展ASCII字符(大于127),使用`String.fromCharCode`仍然可以正确转换,因为JavaScript使用Unicode,而fromCharCode处理的是Unicode码点。但注意,C++中的char可能是带符号的,如果存储负数,则转换时需要注意。通常,我们可以使用`static_cast<unsigned char>`先转换为无符号整数再存储,以避免负数问题。 ### 处理负数或超出ASCII范围的情况 如果char可能是负数(例如某些二进制数据),我们应当将其视为无符号整数: 在C++中: ```cpp unsigned char uchar = static_cast<unsigned char>(myChar); data["charValue"] = static_cast<int>(uchar); ``` 在QML中,我们仍然使用`String.fromCharCode`,因为负数在转换为无符号整数后变成了正数(例如,-1变成255),这样在JavaScript中就可以正确转换了。 ### 总结 在QML中读取QVariantMap中的char值: 1. 在C++中,将char转换为整数(最好是unsigned char再转int)存储到QVariantMap。 2. 在QML中,使用`String.fromCharCode(number)`将整数转换为对应的字符。 如果遇到问题,可以检查存储的整数值是否正确(通过打印),并确保在QML中使用正确的转换方法。 §§相关问题§§ 1. 如何在QML中处理C++传递的二进制数据(byte数组)? 2. 如何将QML中的字符串转换为C++中的char数组? 3. 在QML中如何正确处理非ASCII字符(如中文字符)? 4. 当QVariantMap中包含多种类型的数据时,如何在QML中动态处理?</think>### 在 QML 中读取 QVariantMap 中的 char 值 在 QML 中读取 QVariantMap 中存储的 char 值时,需要注意 char 类型在 C++ 和 QML 之间的转换机制。以下是具体方法和步骤: #### 核心解决方案 1. **C++ 端准备数据** 将 char 值转换为 `int` 或 `QString` 存储,避免直接存储 char 类型: ```cpp QVariantMap data; char myChar = 'A'; // 方法1:转换为 int(推荐) data["charAsInt"] = static_cast<int>(myChar); // 存储 ASCII 值 // 方法2:转换为 QString data["charAsString"] = QString(QChar(myChar)); // 存储为单字符字符串 ``` 2. **QML 端读取转换** ```qml // 读取 int 类型并转换回 char Text { text: "Char value: " + String.fromCharCode(dataMap.charAsInt) } // 直接读取 QString 类型 Text { text: "Char value: " + dataMap.charAsString } ``` #### 完整示例 ##### C++ 端(数据准备) ```cpp // 创建并暴露 QVariantMap QVariantMap createCharData() { QVariantMap data; char char1 = 'X'; char char2 = 'Y'; data["statusFlag"] = static_cast<int>(char1); // 存储为 int data["errorCode"] = QString(QChar(char2)); // 存储为 QString return data; } // 在上下文设置(如 main.cpp) QQuickView view; view.rootContext()->setContextProperty("charData", createCharData()); view.setSource(QUrl("qrc:/main.qml")); view.show(); ``` ##### QML 端(读取和转换) ```qml import QtQuick 2.15 Column { spacing: 10 // 方法1:从 int 转换回 char Text { text: "Status: " + String.fromCharCode(charData.statusFlag) } // 方法2:直接读取 QString Text { text: "Error Code: " + charData.errorCode } // 动态访问示例 function printCharValue(key) { if (typeof charData[key] === "number") { return String.fromCharCode(charData[key]); } return charData[key]; } Component.onCompleted: { console.log("Status:", printCharValue("statusFlag")); // 输出 "X" console.log("Error:", printCharValue("errorCode")); // 输出 "Y" } } ``` #### 关键注意事项 1. **为什么需要转换** QML 的 JavaScript 引擎没有原生 char 类型支持,直接存储 char 会导致: - 自动转换为整数(ASCII 值) - 无法直接作为字符使用 2. **类型处理建议** ```qml // 安全读取方法 function getCharValue(key) { const value = charData[key]; if (typeof value === "number") { // 处理 int 存储 return String.fromCharCode(value); } else if (typeof value === "string") { // 处理 QString 存储 return value.charAt(0); // 取第一个字符 } return ""; // 默认返回空 } ``` 3. **二进制数据处理** 如需处理原始二进制数据(如 `char*`),建议使用 `QByteArray`: ```cpp // C++ 端 QByteArray byteData = "RawData"; data["binary"] = byteData; ``` ```qml // QML 端 const bytes = charData.binary; for (let i = 0; i < bytes.length; ++i) { console.log(String.fromCharCode(bytes[i])); } ``` 4. **特殊字符处理** 非 ASCII 字符(如中文)必须使用 QString 存储: ```cpp char ch = '中'; // 需要宽字符处理 data["chineseChar"] = QString::fromWCharArray(&ch, 1); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值