Qt cpp 遍历list<string> camList 将元素放入QVector<QString> m_vecGuids
时间: 2024-03-16 08:46:04 浏览: 92
可以使用C++11中的range-based for循环来遍历camList,并将元素添加到m_vecGuids中。具体代码如下:
```cpp
#include <QtCore/QString>
#include <QtCore/QVector>
#include <list>
#include <string>
int main()
{
std::list<std::string> camList = {"cam1", "cam2", "cam3"};
QVector<QString> m_vecGuids;
for (const auto& cam : camList)
{
m_vecGuids.append(QString::fromStdString(cam));
}
return 0;
}
```
在循环中,我们使用了`const auto&`来声明一个常量引用,以便在循环中访问camList中的每个元素。然后,我们使用`QString::fromStdString()`将std::string类型的cam转换为QString类型,并将其添加到m_vecGuids中。
相关问题
D:\QT_project\wifishiyan\wifi.cpp:73: error: No viable conversion from 'QList<int>' to 'const QList<QString>'
<think>好的,我现在要解决用户遇到的编译错误:如何将 `QList<int>` 转换为 `const QList<QString>`。首先,我需要了解问题的根源。用户可能在尝试将整数列表转换为字符串列表时遇到了类型不匹配的错误,因为Qt的容器类不支持隐式转换。
根据引用[5]提到的错误信息,类似的情况是尝试将 `QList<QByteArray>` 转换为 `QList<QString>` 时失败。这说明Qt的容器类型之间不能直接转换,即使元素类型可以转换。因此,用户需要显式地将每个元素从 `int` 转换为 `QString`,然后构造新的 `QList<QString>`。
接下来,我需要考虑如何实现这种转换。在Qt中,可以使用循环遍历原始列表,逐个转换元素。例如,使用 `QList` 的 `append` 方法,或者利用Qt的算法库中的 `std::transform` 函数。此外,C++11的基于范围的for循环可能更简洁。
另外,引用[3]和引用[4]提供了Qt中操作 `QList` 的示例代码,展示了如何添加元素和遍历列表,这可以作为参考。例如,方法二中的for-each循环可能适用于此场景。
需要注意的是,直接类型转换(如`reinterpret_cast`)是不可行的,因为 `QList<int>` 和 `QList<QString>` 是不同的模板实例化,内存布局不同。因此,必须逐个元素转换。
最后,应该建议用户检查是否有必要进行这种转换,或者是否可以通过其他方式避免类型转换,比如在数据源处直接生成 `QList<QString>`。此外,还要提醒用户注意转换过程中的性能开销,特别是在处理大型列表时。</think>### 从 `QList<int>` 到 `const QList<QString>` 的转换错误分析
#### 问题原因
Qt 的容器类(如 `QList<T>`)是模板类,不同模板实例化类型之间无法直接隐式转换。例如,`QList<int>` 和 `QList<QString>` 属于不同的类型,编译器会拒绝隐式转换请求[^5]。错误类似于:
```cpp
error: no viable conversion from 'QList<int>' to 'const QList<QString>'
```
---
#### 解决方案
##### 方法 1:手动遍历转换
通过遍历 `QList<int>` 的每个元素,将其转换为 `QString` 并存入新列表:
```cpp
QList<int> intList = {1, 2, 3, 4};
QList<QString> stringList;
// 遍历转换
for (int num : intList) {
stringList.append(QString::number(num));
}
// 转换为 const 引用(无需拷贝)
const QList<QString>& constStringList = stringList;
```
##### 方法 2:使用 `std::transform` 算法
通过 C++ 标准库算法实现高效转换:
```cpp
#include <algorithm>
QList<int> intList = {1, 2, 3, 4};
QList<QString> stringList;
stringList.reserve(intList.size()); // 预分配空间提升性能
// 转换逻辑
std::transform(intList.begin(), intList.end(), std::back_inserter(stringList),
[](int num) { return QString::number(num); });
```
---
#### 关键注意事项
1. **类型安全**:`int` 到 `QString` 必须显式转换,例如通过 `QString::number()` 或 `QVariant`[^3][^4]。
2. **性能优化**:对大列表建议预分配内存(`reserve()`)以减少动态扩容开销。
3. **Qt 容器特性**:`QList<T>` 在 Qt 6 中已与 `QVector<T>` 合并,底层为连续内存布局[^2]。
---
#### 错误示例修正
若原始代码尝试直接赋值:
```cpp
QList<int> intList;
const QList<QString>& stringList = intList; // 错误!
```
应改为显式转换:
```cpp
QList<QString> stringList = convertIntListToStringList(intList); // 自定义转换函数
```
---
<html><head><meta http-equiv="Content-Type" content="text/html; charset= =iso-8859-1"> <title>Trioptics Certificate</title> <link type="text/css" rel="stylesheet" href="certificate.css"></link> <base href="file:///C:/Program%20Files%20(x86)/TRIOPTICS%20GmbH/MTF-LAB%2= 05/Certificates/"></base></head> <body id="IBodyCert" class="CBodyCert"> <!-- open certificate table --> <table align="left" id="ITableCert" class="CTableCert"> <!-- Header --> <tbody><tr id="ITRCompany" class="CTRHeader"> <td id="ITDCompany" class="CTDHeader"> <div id="IDivCompany" class="CDivHeader">ImageMaster - Certificate</div> </td> <td id="ITDLogo" class="CTDHeader"> <img src="./img/Trioptics-Logo-250x65.png" id="ITDLogo" class="CTDHea= der"> </td> </tr> <tr id="ITDSlogan" class="CTRHeader"> <td colspan="2" id="ITDSlogan" class="CTDHeader"> </td> </tr> <tr> <td colspan="2"> <pre>Company : ****** Operator : ****** Time/Date : 13:30:33 June 12, 2025 Sample ID : ****** Measure Program : MTF vs. Field Temperature : 20°C Measured with : <a href="http://www.trioptics.com/">TRIOPTICS</a> - MT= F-LAB - Vers. 5.16.1 Instrument S/N : 09-113-0519 Comments : SN215U0540 </pre> </td> </tr> <tr> <td colspan="2"> </td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Parameter: MTF vs. Image Height</b> <pre>Setup Type : Object Infinite / Image Finite EFL (Collimator): 50 mm Wavelength : 940 nm (NIR) EFL (Sample) : 1.5550 mm F-Number : 2.0000 Object Angle : -0.0198 ° Focus Position : 85.8471 Sample Azimuth : 0.0 ° </pre></td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Graph: MTF vs. Image Height</b> <br><br> <right> <img src="Chart12.png"> </right> </td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Table: MTF vs. Image Height</b> <br><br> <!-- open measurement table --> <table cellspacing="0" align="left" id="ITableDataItems" class="CTa= bleDataItems"> <!-- begin table caption --> <tbody><tr id="ITRDataCaption" class="CTRDataCaption"> <td id="ITDCaptionBlank" class="CTDCaptionBlank"></td> <td align="center" colspan="5" id="ITDDataCaption" class="CTDDataCa= ption">Image Height (mm)</td> </tr> <tr id="ITRDataCaption" class="CTRDataCaption"> <td id="ITDDataCaption" class="CTDDataCaption">MTF</td> <td id="ITDDataCaption" class="CTDDataCaption">0.42800</td> <td id="ITDDataCaption" class="CTDDataCaption">0.29960</td> <td id="ITDDataCaption" class="CTDDataCaption">-0.00114</td> <td id="ITDDataCaption" class="CTDDataCaption">-0.29960</td> <td id="ITDDataCaption" class="CTDDataCaption">-0.42800</td> <td id="ITDDataCaption" class="CTDDataCaption">Legend</td> </tr> <!-- end table caption --> <!-- begin measurement data --> <tr id="ITRDataItem" class="CTRDataItem"> <td id="ITDEven" class="CTDDataItem">Tan 100(lp/mm)</td> <td id="ITDEven" class="CTDDataItem">0.599</td> <td id="ITDEven" class="CTDDataItem">0.677</td> <td id="ITDEven" class="CTDDataItem">0.668</td> <td id="ITDEven" class="CTDDataItem">0.703</td> <td id="ITDEven" class="CTDDataItem">0.645</td> <td colspan="1" id="ITDLegend" class="CTDLegend"><font color="ff000= 0">— — —</font></td> </tr> <tr id="ITRDataItem" class="CTRDataItem"> <td id="ITDEven" class="CTDDataItem">Sag 100(lp/mm)</td> <td id="ITDEven" class="CTDDataItem">0.558</td> <td id="ITDEven" class="CTDDataItem">0.659</td> <td id="ITDEven" class="CTDDataItem">0.673</td> <td id="ITDEven" class="CTDDataItem">0.688</td> <td id="ITDEven" class="CTDDataItem">0.642</td> <td colspan="1" id="ITDLegend" class="CTDLegend"><font color="ff000= 0">————</font></td> </tr> <!-- end measurement data --> <!-- close measurement table --> </tbody></table><br clear="all"> </td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Parameter: MTF vs. Object Angle</b> <pre>Setup Type : Object Infinite / Image Finite EFL (Collimator): 50 mm Wavelength : 940 nm (NIR) EFL (Sample) : 1.5550 mm F-Number : 2.0000 Object Angle : -0.0198 ° Focus Position : 85.8471 Sample Azimuth : 0.0 ° </pre></td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Graph: MTF vs. Object Angle</b> <br><br> <right> <img src="Chart11.png"> </right> </td> </tr> <tr> <td colspan="2"> <hr> <b>Measurement Table: MTF vs. Object Angle</b> <br><br> <!-- open measurement table --> <table cellspacing="0" align="left" id="ITableDataItems" class="CTa= bleDataItems"> <!-- begin table caption --> <tbody><tr id="ITRDataCaption" class="CTRDataCaption"> <td id="ITDCaptionBlank" class="CTDCaptionBlank"></td> <td align="center" colspan="5" id="ITDDataCaption" class="CTDDataCa= ption">Object Angle (?</td> </tr> <tr id="ITRDataCaption" class="CTRDataCaption"> <td id="ITDDataCaption" class="CTDDataCaption">MTF</td> <td id="ITDDataCaption" class="CTDDataCaption">-15.33590</td> <td id="ITDDataCaption" class="CTDDataCaption">-10.72937</td> <td id="ITDDataCaption" class="CTDDataCaption">0.00072</td> <td id="ITDDataCaption" class="CTDDataCaption">10.77662</td> <td id="ITDDataCaption" class="CTDDataCaption">15.40352</td> <td id="ITDDataCaption" class="CTDDataCaption">Legend</td> </tr> <!-- end table caption --> <!-- begin measurement data --> <tr id="ITRDataItem" class="CTRDataItem"> <td id="ITDEven" class="CTDDataItem">Tan 100(lp/mm)</td> <td id="ITDEven" class="CTDDataItem">0.599</td> <td id="ITDEven" class="CTDDataItem">0.677</td> <td id="ITDEven" class="CTDDataItem">0.668</td> <td id="ITDEven" class="CTDDataItem">0.703</td> <td id="ITDEven" class="CTDDataItem">0.645</td> <td colspan="1" id="ITDLegend" class="CTDLegend"><font color="ff000= 0">— — —</font></td> </tr> <tr id="ITRDataItem" class="CTRDataItem"> <td id="ITDEven" class="CTDDataItem">Sag 100(lp/mm)</td> <td id="ITDEven" class="CTDDataItem">0.558</td> <td id="ITDEven" class="CTDDataItem">0.659</td> <td id="ITDEven" class="CTDDataItem">0.673</td> <td id="ITDEven" class="CTDDataItem">0.688</td> <td id="ITDEven" class="CTDDataItem">0.642</td> <td colspan="1" id="ITDLegend" class="CTDLegend"><font color="ff000= 0">————</font></td> </tr> <!-- end measurement data --> <!-- close measurement table --> </tbody></table><br clear="all"> </td> </tr> <!-- close certificate table --> </tbody></table> </body></html> 解析这个
<think>我们面对的是一个HTML格式的证书报告,需要从中提取关键信息。报告包含多个部分:标题、公司信息、测量参数、图表和测量数据表格。目标:提取以下信息:1.头部信息(如公司、操作员、时间日期、样品ID、测量程序、温度、仪器序列号、注释等)2.测量参数(如SetupType,EFL,Wavelength,F-Number,ObjectAngle,FocusPosition,SampleAzimuth等)3.测量表格数据(包括表格的标题行和数据行)注意:报告中有两个测量部分(MTFvs.ImageHeight和MTFvs.ObjectAngle),每个部分包含一个表格。策略:1.使用HTML解析库(如Qt的QDomDocument)来解析HTML。2.定位到各个关键部分,提取文本信息。3.对于表格,我们需要解析表头(第一行)和数据行。步骤:a.解析头部信息:这些信息在<pre>标签内,格式为键值对。b.解析测量参数:同样在<pre>标签内,但位于不同的部分(通过前面的标题来区分)。c.解析表格:每个表格位于一个<table>内,并且有特定的结构。难点:表格结构相对固定,但需要处理多个表格,并且每个表格的列数可能不同(但在这个例子中都是相同的结构)。我们将设计一个解析器,提取以下结构的数据:structMeasurementParams{QStringsetupType;QStringeflCollimator;QStringwavelength;QStringeflSample;QStringfNumber;QStringobjectAngle;QStringfocusPosition;QStringsampleAzimuth;};structTableData{QStringcaption;//表格标题(例如:ImageHeight(mm)或ObjectAngle(?))QStringListheaders;//表头(第一行:MTF,然后是一系列数值,最后是Legend)QList<QStringList>rows;//每一行数据(第一列是参数名,然后是数值,最后是图例符号)};structCertificateData{//头部信息QStringcompany;QStringoperatorName;QDateTimetimeDate;QStringsampleId;QStringmeasureProgram;QStringtemperature;QStringinstrument;QStringinstrumentSN;QStringcomments;//测量参数1(MTFvs.ImageHeight)MeasurementParamsparams1;QStringgraphImage1;//图表文件名,如Chart12.pngTableDatatableData1;//测量参数2(MTFvs.ObjectAngle)MeasurementParamsparams2;QStringgraphImage2;//图表文件名,如Chart11.pngTableDatatableData2;};实现步骤:1.加载HTML文档。2.提取头部信息:在第一个<pre>标签中。3.提取第一个测量参数部分:在第一个"MeasurementParameter:MTFvs.ImageHeight"后面的<pre>中。4.提取第一个图表:在第一个"MeasurementGraph"后面的<img>标签的src属性。5.提取第一个表格:在第一个"MeasurementTable"后面的<table>中。6.同样提取第二个测量参数部分、图表和表格。注意:由于HTML结构复杂,我们通过查找特定的文本来定位各部分。我们将使用递归遍历DOM树,并查找特定的文本节点来定位。由于HTML中可能包含多个<pre>和<table>,我们根据上下文来区分。具体实现:我们将遍历DOM树,同时记录当前的状态(例如,是否在头部、是否在第一个测量部分等)。考虑到时间,我们设计一个状态机来解析。然而,由于这个HTML结构相对固定,我们可以通过查找特定的标题文本来定位。例如:-头部信息:在第一个<pre>标签中,且该<pre>在第一个<hr>之前。-第一个测量参数:在包含"MeasurementParameter:MTFvs.ImageHeight"的<b>标签之后的下一个<pre>标签。由于HTML中使用了表格布局,我们需要注意嵌套。简化:我们使用QDomDocument,并通过查找文本节点来定位。步骤:1.查找所有<b>节点,通过文本内容判断是哪个部分。2.对于每个<b>节点,如果文本包含"MeasurementParameter",则下一个<pre>节点就是参数。3.同样,如果包含"MeasurementGraph",则下一个<img>节点就是图表。4.如果包含"MeasurementTable",则下一个<table>节点就是数据表格。头部信息在第一个<b>之前,第一个<pre>中。代码实现:由于HTML文档较大,我们只关注关键部分。注意,HTML中可能有编码问题(如=iso-8859-1),但Qt可以处理。开始编写代码:</think># Trioptics 证书报告解析方案
我将提供一个完整的解决方案来解析 Trioptics 证书报告 HTML 文件,提取所有关键信息和测量数据。
## 完整解析代码
```cpp
#include <QCoreApplication>
#include <QFile>
#include <QDebug>
#include <QDomDocument>
#include <QRegularExpression>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonArray>
// 数据结构定义
struct HeaderInfo {
QString company;
QString operatorName;
QDateTime dateTime;
QString sampleId;
QString measureProgram;
QString temperature;
QString instrument;
QString instrumentSN;
QString comments;
};
struct MeasurementParam {
QString setupType;
QString eflCollimator;
QString wavelength;
QString eflSample;
QString fNumber;
QString objectAngle;
QString focusPosition;
QString sampleAzimuth;
};
struct TableData {
QString caption;
QStringList headers;
QList<QStringList> rows;
};
struct MeasurementSection {
QString title;
MeasurementParam params;
QString graphImage;
TableData tableData;
};
struct CertificateData {
HeaderInfo header;
QList<MeasurementSection> sections;
};
// HTML 解析器
CertificateData parseCertificateHtml(const QString& htmlContent) {
CertificateData certificate;
QDomDocument doc;
if (!doc.setContent(htmlContent)) {
qWarning() << "Failed to parse HTML content";
return certificate;
}
// 解析头部信息
QDomNodeList preNodes = doc.elementsByTagName("pre");
if (preNodes.size() > 0) {
QString headerText = preNodes.at(0).toElement().text();
QRegularExpression re("Company\\s+:\\s+(.*)\n"
"Operator\\s+:\\s+(.*)\n"
"Time/Date\\s+:\\s+(.*)\n"
"Sample ID\\s+:\\s+(.*)\n"
"Measure Program\\s+:\\s+(.*)\n"
"Temperature\\s+:\\s+(.*)\n"
"Measured with\\s+:\\s+(.*)\n"
"Instrument S/N\\s+:\\s+(.*)\n"
"Comments\\s+:\\s+(.*)");
QRegularExpressionMatch match = re.match(headerText);
if (match.hasMatch()) {
certificate.header.company = match.captured(1);
certificate.header.operatorName = match.captured(2);
certificate.header.dateTime = QDateTime::fromString(match.captured(3).trimmed(), "hh:mm:ss MMMM d, yyyy");
certificate.header.sampleId = match.captured(4);
certificate.header.measureProgram = match.captured(5);
certificate.header.temperature = match.captured(6);
certificate.header.instrument = match.captured(7);
certificate.header.instrumentSN = match.captured(8);
certificate.header.comments = match.captured(9);
}
}
// 查找所有测量部分
QDomNodeList bNodes = doc.elementsByTagName("b");
QDomNodeList tableNodes = doc.elementsByTagName("table");
QDomNodeList imgNodes = doc.elementsByTagName("img");
int sectionIndex = 0;
int tableIndex = 0;
int imgIndex = 0;
// 遍历所有<b>标签找到测量部分标题
for (int i = 0; i < bNodes.size(); i++) {
QString title = bNodes.at(i).toElement().text();
if (title.startsWith("Measurement Parameter:") ||
title.startsWith("Measurement Graph:") ||
title.startsWith("Measurement Table:")) {
if (title.startsWith("Measurement Parameter:")) {
// 开始新的测量部分
MeasurementSection section;
section.title = title.mid(24); // 移除"Measurement Parameter: "
// 获取参数信息
if (i + 1 < bNodes.size()) {
QDomElement nextElement = bNodes.at(i+1).nextSiblingElement();
if (nextElement.tagName() == "pre") {
QString paramText = nextElement.text();
QRegularExpression paramRe("Setup Type\\s+:\\s+(.*)\n"
"EFL \\(Collimator\\):\\s+(.*)\n"
"Wavelength\\s+:\\s+(.*)\n"
"EFL \\(Sample\\):\\s+(.*)\n"
"F-Number\\s+:\\s+(.*)\n"
"Object Angle\\s+:\\s+(.*)\n"
"Focus Position\\s+:\\s+(.*)\n"
"Sample Azimuth\\s+:\\s+(.*)");
QRegularExpressionMatch paramMatch = paramRe.match(paramText);
if (paramMatch.hasMatch()) {
section.params.setupType = paramMatch.captured(1);
section.params.eflCollimator = paramMatch.captured(2);
section.params.wavelength = paramMatch.captured(3);
section.params.eflSample = paramMatch.captured(4);
section.params.fNumber = paramMatch.captured(5);
section.params.objectAngle = paramMatch.captured(6);
section.params.focusPosition = paramMatch.captured(7);
section.params.sampleAzimuth = paramMatch.captured(8);
}
}
}
// 获取图表
if (imgIndex < imgNodes.size()) {
section.graphImage = imgNodes.at(imgIndex).toElement().attribute("src");
imgIndex++;
}
// 获取表格数据
if (tableIndex < tableNodes.size()) {
QDomElement table = tableNodes.at(tableIndex).toElement();
tableIndex++;
TableData tableData;
// 提取表格标题
QDomNodeList captionCells = table.elementsByTagName("td");
if (captionCells.size() > 1) {
QDomElement captionCell = captionCells.at(1).toElement();
if (captionCell.attribute("id") == "ITDDataCaption" &&
captionCell.attribute("class") == "CTDDataCaption") {
tableData.caption = captionCell.text();
}
}
// 提取表头
QDomNodeList headerRows = table.elementsByTagName("tr");
if (headerRows.size() > 1) {
QDomElement headerRow = headerRows.at(1).toElement();
QDomNodeList headerCells = headerRow.elementsByTagName("td");
for (int h = 0; h < headerCells.size(); h++) {
tableData.headers << headerCells.at(h).toElement().text().trimmed();
}
}
// 提取数据行
for (int r = 2; r < headerRows.size(); r++) {
QDomElement dataRow = headerRows.at(r).toElement();
if (dataRow.attribute("id") == "ITRDataItem") {
QDomNodeList dataCells = dataRow.elementsByTagName("td");
QStringList rowData;
for (int c = 0; c < dataCells.size(); c++) {
rowData << dataCells.at(c).toElement().text().trimmed();
}
tableData.rows << rowData;
}
}
section.tableData = tableData;
}
certificate.sections << section;
sectionIndex++;
}
}
}
return certificate;
}
// 导出为JSON格式
QString exportToJson(const CertificateData& certificate) {
QJsonObject json;
// 头部信息
QJsonObject header;
header["company"] = certificate.header.company;
header["operator"] = certificate.header.operatorName;
header["date_time"] = certificate.header.dateTime.toString(Qt::ISODate);
header["sample_id"] = certificate.header.sampleId;
header["measure_program"] = certificate.header.measureProgram;
header["temperature"] = certificate.header.temperature;
header["instrument"] = certificate.header.instrument;
header["instrument_sn"] = certificate.header.instrumentSN;
header["comments"] = certificate.header.comments;
json["header"] = header;
// 测量部分
QJsonArray sections;
for (const MeasurementSection& section : certificate.sections) {
QJsonObject sectionObj;
sectionObj["title"] = section.title;
// 参数
QJsonObject params;
params["setup_type"] = section.params.setupType;
params["efl_collimator"] = section.params.eflCollimator;
params["wavelength"] = section.params.wavelength;
params["efl_sample"] = section.params.eflSample;
params["f_number"] = section.params.fNumber;
params["object_angle"] = section.params.objectAngle;
params["focus_position"] = section.params.focusPosition;
params["sample_azimuth"] = section.params.sampleAzimuth;
sectionObj["params"] = params;
// 图表
sectionObj["graph_image"] = section.graphImage;
// 表格数据
QJsonObject table;
table["caption"] = section.tableData.caption;
QJsonArray headers;
for (const QString& h : section.tableData.headers) {
headers.append(h);
}
table["headers"] = headers;
QJsonArray rows;
for (const QStringList& row : section.tableData.rows) {
QJsonArray rowArray;
for (const QString& cell : row) {
rowArray.append(cell);
}
rows.append(rowArray);
}
table["rows"] = rows;
sectionObj["table_data"] = table;
sections.append(sectionObj);
}
json["sections"] = sections;
return QJsonDocument(json).toJson(QJsonDocument::Indented);
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 从文件加载HTML内容
QFile file("certificate.html");
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed to open file";
return 1;
}
QString htmlContent = file.readAll();
file.close();
// 解析证书
CertificateData certificate = parseCertificateHtml(htmlContent);
// 导出为JSON
QString json = exportToJson(certificate);
qDebug().noquote() << json;
return a.exec();
}
```
## 代码详细解释
### 1. 数据结构设计
```cpp
// 头部信息
struct HeaderInfo {
QString company;
QString operatorName;
QDateTime dateTime;
QString sampleId;
QString measureProgram;
QString temperature;
QString instrument;
QString instrumentSN;
QString comments;
};
// 测量参数
struct MeasurementParam {
QString setupType;
QString eflCollimator;
QString wavelength;
QString eflSample;
QString fNumber;
QString objectAngle;
QString focusPosition;
QString sampleAzimuth;
};
// 表格数据
struct TableData {
QString caption;
QStringList headers;
QList<QStringList> rows;
};
// 测量部分
struct MeasurementSection {
QString title;
MeasurementParam params;
QString graphImage;
TableData tableData;
};
// 完整证书数据
struct CertificateData {
HeaderInfo header;
QList<MeasurementSection> sections;
};
```
这种结构完整保留了报告中的所有关键信息,包括:
- 证书头部信息(公司、操作员、日期等)
- 测量参数(设置类型、波长、焦距等)
- 图表文件路径
- 表格数据(标题、表头、测量值)
### 2. 解析流程
```cpp
CertificateData parseCertificateHtml(const QString& htmlContent) {
CertificateData certificate;
QDomDocument doc;
doc.setContent(htmlContent);
// 1. 解析头部信息(第一个<pre>标签)
// 2. 查找所有<b>标签定位测量部分
// 3. 对每个测量部分:
// a. 提取标题
// b. 解析参数(<pre>标签)
// c. 提取图表(<img>标签)
// d. 解析表格数据(<table>标签)
// 4. 返回完整证书数据
}
```
### 3. 关键解析技术
**头部信息解析:**
```cpp
QRegularExpression re("Company\\s+:\\s+(.*)\n"
"Operator\\s+:\\s+(.*)\n"
"Time/Date\\s+:\\s+(.*)\n"
"Sample ID\\s+:\\s+(.*)\n"
"Measure Program\\s+:\\s+(.*)\n"
"Temperature\\s+:\\s+(.*)\n"
"Measured with\\s+:\\s+(.*)\n"
"Instrument S/N\\s+:\\s+(.*)\n"
"Comments\\s+:\\s+(.*)");
```
**测量参数解析:**
```cpp
QRegularExpression paramRe("Setup Type\\s+:\\s+(.*)\n"
"EFL \\(Collimator\\):\\s+(.*)\n"
"Wavelength\\s+:\\s+(.*)\n"
"EFL \\(Sample\\):\\s+(.*)\n"
"F-Number\\s+:\\s+(.*)\n"
"Object Angle\\s+:\\s+(.*)\n"
"Focus Position\\s+:\\s+(.*)\n"
"Sample Azimuth\\s+:\\s+(.*)");
```
**表格数据解析:**
```cpp
// 提取表格标题
QDomElement captionCell = captionCells.at(1).toElement();
tableData.caption = captionCell.text();
// 提取表头
QDomNodeList headerCells = headerRow.elementsByTagName("td");
for (int h = 0; h < headerCells.size(); h++) {
tableData.headers << headerCells.at(h).toElement().text().trimmed();
}
// 提取数据行
QDomNodeList dataCells = dataRow.elementsByTagName("td");
QStringList rowData;
for (int c = 0; c < dataCells.size(); c++) {
rowData << dataCells.at(c).toElement().text().trimmed();
}
tableData.rows << rowData;
```
### 4. JSON 导出格式
```json
{
"header": {
"company": "******",
"operator": "******",
"date_time": "2025-06-12T13:30:33",
"sample_id": "******",
"measure_program": "MTF vs. Field",
"temperature": "20°C",
"instrument": "TRIOPTICS - MTF-LAB - Vers. 5.16.1",
"instrument_sn": "09-113-0519",
"comments": "SN215U0540"
},
"sections": [
{
"title": "MTF vs. Image Height",
"params": {
"setup_type": "Object Infinite / Image Finite",
"efl_collimator": "50 mm",
"wavelength": "940 nm (NIR)",
"efl_sample": "1.5550 mm",
"f_number": "2.0000",
"object_angle": "-0.0198 °",
"focus_position": "85.8471",
"sample_azimuth": "0.0 °"
},
"graph_image": "Chart12.png",
"table_data": {
"caption": "Image Height (mm)",
"headers": ["MTF", "0.42800", "0.29960", ...],
"rows": [
["Tan 100(lp/mm)", "0.599", "0.677", ...],
["Sag 100(lp/mm)", "0.558", "0.659", ...]
]
}
},
{
"title": "MTF vs. Object Angle",
// 类似结构...
}
]
}
```
## 扩展功能:图表数据处理
对于报告中的图表,我们可以进一步处理图像数据:
```cpp
// 图像数据处理类
class ImageProcessor {
public:
// 从Base64数据加载图像
static QImage loadFromBase64(const QString& base64Data) {
QByteArray imageData = QByteArray::fromBase64(base64Data.toUtf8());
QImage image;
image.loadFromData(imageData);
return image;
}
// 分析图表图像,提取数据点
static QVector<QPointF> extractDataPoints(const QImage& chartImage) {
QVector<QPointF> dataPoints;
// 图像处理逻辑
// 1. 识别坐标轴位置
// 2. 检测曲线像素点
// 3. 转换为数据坐标
return dataPoints;
}
// 导出图表为CSV
static void exportChartToCsv(const QVector<QPointF>& dataPoints, const QString& filename) {
QFile file(filename);
if (file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << "X,Y\n";
for (const QPointF& point : dataPoints) {
stream << point.x() << "," << point.y() << "\n";
}
}
}
};
```
## 应用场景
1. **自动化报告处理**:
```python
# Python脚本调用
import subprocess
# 调用C++解析器
result = subprocess.run(["./certificate_parser", "input.html", "output.json"],
capture_output=True, text=True)
# 处理JSON结果
import json
data = json.loads(result.stdout)
```
2. **数据库存储**:
```sql
CREATE TABLE measurement_data (
id INT AUTO_INCREMENT PRIMARY KEY,
sample_id VARCHAR(50),
measurement_type VARCHAR(50),
parameter VARCHAR(50),
value1 FLOAT,
value2 FLOAT,
value3 FLOAT,
value4 FLOAT,
value5 FLOAT,
timestamp DATETIME
);
```
3. **质量控制系统集成**:
```cpp
// 检查MTF值是否符合标准
bool checkMtfCompliance(const CertificateData& data) {
for (const MeasurementSection& section : data.sections) {
for (const QStringList& row : section.tableData.rows) {
if (row.size() > 1) {
for (int i = 1; i < row.size(); i++) {
bool ok;
double value = row[i].toDouble(&ok);
if (ok && value < 0.6) { // MTF阈值
return false;
}
}
}
}
}
return true;
}
```
## 性能优化
对于大量证书处理:
```cpp
// 多线程处理
void processCertificates(const QStringList& filePaths) {
QThreadPool pool;
pool.setMaxThreadCount(QThread::idealThreadCount());
for (const QString& filePath : filePaths) {
QtConcurrent::run(&pool, [filePath]() {
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
CertificateData data = parseCertificateHtml(file.readAll());
QString json = exportToJson(data);
// 保存或发送结果
}
});
}
pool.waitForDone();
}
```
阅读全文
相关推荐















