笑话理解之Denomination

一位女士走进邮局购买圣诞节卡片的邮票,当被问及要什么面额时,她幽默地回答要50张浸信会、50张天主教和一张卫理宗的邮票。这个故事巧妙地玩弄了denomination一词的双重含义——既指邮票面额也指宗教派别。
#include "mainwindow.h" #include <QFileDialog> #include <QFile> #include <QMessageBox> #include <QHeaderView> #include <QDebug> #include <QRegularExpression> #include <QSettings> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { centralWidget = new QWidget(this); mainLayout = new QVBoxLayout(centralWidget); treeWidget = new QTreeWidget(this); treeWidget->setHeaderLabels(QStringList() << "分类" << "IR_R" << "IR_T"); //treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents); treeWidget->setColumnWidth(0,140); treeWidget->setColumnWidth(1,100); treeWidget->setColumnWidth(2,100); treeWidget->setStyleSheet("background-color:white;color:black;font-size:15px;"); browseButton = new QPushButton("选择BIN文件",this); browseButton->setStyleSheet("background-color:white;color:black;font-size:15px;"); browseButton->setMinimumHeight(40); mainLayout->addWidget(browseButton); mainLayout->addWidget(treeWidget); setCentralWidget(centralWidget); connect(browseButton,&QPushButton::clicked,this,&MainWindow::onBrowseButtonClicked); setWindowTitle("BIN文件查看器"); resize(800,600); } MainWindow::~MainWindow() { } void MainWindow::onBrowseButtonClicked() { QSettings settings("./Setting.ini", QSettings::IniFormat); QString lastPath = settings.value("LastFilePath").toString(); //获取上次的打开路径 QString filePath = QFileDialog::getOpenFileName(this,"选择SIZE文件",lastPath); if (!filePath.isEmpty()) { settings.setValue("lastFilePath", filePath); } if(!filePath.isEmpty()) { //从文件路径提取币种信息 QRegularExpression re("CISW1_(\\w{3})\\.bin$"); QRegularExpressionMatch match = re.match(filePath); if(match.hasMatch()) { m_currency = match.captured(1); } //获取对应的文件夹路径 QFileInfo fileInfo(filePath); m_folderPath = fileInfo.absolutePath(); parseBinFile(filePath); displayData(); } } //处理BIN文件 void MainWindow::parseBinFile(const QString &filePath) { //清空数据存储 m_data.clear(); m_folderIndex.clear(); //清空索引 buildFolderIndex(); //构建文件夹索引 QFile file(filePath); if(!file.open(QIODevice::ReadOnly)) { QMessageBox::warning(this,"错误","无法打开文件"); return; } //读取全部数据存入QByteArray对象 QByteArray data = file.readAll(); file.close(); //查找"SIZE"第一次出现的位置(53 49 5A 45) const char sizeMarker[] = {0x53, 0x49, 0x5A, 0x45}; int startPos = data.indexOf(sizeMarker); if(startPos == -1) { QMessageBox::warning(this,"错误","未找到SIZE标记"); return; } //从SIZE标记后开始解析数据 const uchar* fileData = reinterpret_cast<const uchar*>(data.constData() + startPos + 64); const int fileSize = data.size() - startPos - 64; const int recordSize = 16; const int maxRecords = fileSize/recordSize; //标志是否已经读取到有效数据的末尾 bool endOfVaildData = false; //记录连续全零记录的数量 int consecutiveZeroRecords = 0; const int maxConsecutiveZeroRecords = 12; //允许的最大的连续记录为0的行数,一般最多是三组,也就是十二个为0 for(int i = 1;i < maxRecords && !endOfVaildData; ++i) { //记录第一次size标记后面的每一行 const uchar* record = fileData + i * recordSize; //检查在没超过文件大小的情况下是否遇到新的SIZE标记 if(i*recordSize + 4 <= fileSize && memcmp(record,sizeMarker,4) == 0) { endOfVaildData = true; break; } //检查记录是否全零 bool isZeroRecord = true; for(int j = 0;j < recordSize;++j) { if(record[j] != 0) { isZeroRecord = false; break; } } if(isZeroRecord) { consecutiveZeroRecords++; //如果连续遇到太多全零记录,就认为是到达有效数据末尾 if(consecutiveZeroRecords >= maxConsecutiveZeroRecords) { endOfVaildData = true; break; } //continue; } else { consecutiveZeroRecords = 0; //重置计数器 } //解析关键字段 int ir_r = static_cast<int>(record[5]); int ir_t = static_cast<int>(record[6]); int irts = record[7]; //使用索引获取文件夹信息 if(m_folderIndex.contains(i)) { FolderInfo info = m_folderIndex[i]; //存储数据 m_data[info.denomination][info.year][info.version] = {ir_r, ir_t, irts}; }else { qDebug() << "警告: 记录" << i << "没有对应的文件夹索引"; } } } void MainWindow::buildFolderIndex() { m_folderIndex.clear(); int recordCounter = 1; //从1开始,跳过全局记录 QDir dir(m_folderPath); QStringList types = {"white", "IR_T", "IR_R"}; foreach (const QString &type, types) { QDir typeDir(m_folderPath + "/" + type); if(!typeDir.exists()) continue; //获取面额文件夹并排序 QStringList denomDirs = typeDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); std::sort(denomDirs.begin(), denomDirs.end(), [](const QString &a, const QString &b) { return a.toInt() > b.toInt(); //降序排序 }); foreach (const QString &denom, denomDirs) { QDir denomDir(typeDir.path() + "/" + denom); //获取年份文件夹并排序 QStringList yearDirs = denomDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); std::sort(yearDirs.begin(), yearDirs.end(), [](const QString &a, const QString &b) { return a.toInt() > b.toInt(); //降序排序 }); foreach(const QString &year, yearDirs) { QDir yearDir(denomDir.path() + "/" + year); //获取版本文件夹 QStringList versionDirs = yearDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); foreach(const QString &version, versionDirs) { //为每个版本分配1个记录索引(移除for循环) if(recordCounter < 1024) { //防止溢出 m_folderIndex[recordCounter++] = { denom, year, version, type }; } } } } } } QString MainWindow::getFolderPathForRecord(int recordIndex) { //计算组索引(每组4个记录对应A/B/C/D版本) int groupIndex = (recordIndex - 1) / 4; //遍历文件夹结构查找对应的路径 QDir dir(m_folderPath); QStringList folders; //搜索white、IR_T、IR_R子文件夹 QStringList types = {"white", "IR_T", "IR_R"}; foreach(const QString &type, types) { QDir typeDir(m_folderPath + "/" + type); if(typeDir.exists()) { //搜索面额文件夹 QStringList denomDirs = typeDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); foreach(const QString &denom, denomDirs) { QDir denomDir(typeDir.path() + "/" + denom); //搜索年份文件夹 QStringList yearDirs = denomDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); foreach(const QString &year, yearDirs) { QDir yearDir(denomDir.path() + "/" + year); //搜索版本文件夹(A/B/C/D) QStringList versionDirs = yearDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); foreach(const QString &version, versionDirs) { //检查是否是我们需要的记录 if(--groupIndex < 0) { return typeDir.path() + "/" + denom + "/" + year + "/" + version; } } } } } } return QString(); } void MainWindow::displayData() { treeWidget->clear(); //获取排序后的面额列表(降序) QStringList denominations = m_data.keys(); std::sort(denominations.begin(), denominations.end(), [](const QString &a, const QString &b) { return a.toInt() > b.toInt(); }); //按面额分类 foreach(const QString &denomination, denominations) { //跳过面额为10000000的记录 if(denomination == "10000000") { continue; } QTreeWidgetItem *denomItem = new QTreeWidgetItem(treeWidget); denomItem->setText(0, "面额: " + denomination); //获取排序后的年份列表(降序) QStringList years = m_data[denomination].keys(); std::sort(years.begin(), years.end(), [](const QString &a, const QString &b) { return a.toInt() > b.toInt(); }); //按年份分类 foreach(const QString &year, years) { QTreeWidgetItem *yearItem = new QTreeWidgetItem(denomItem); yearItem->setText(0, "年份: " + year); //按版本分类 QMap<QString, CurrencyData> versions = m_data[denomination][year]; foreach(const QString &version, versions.keys()) { CurrencyData data = versions[version]; QTreeWidgetItem *versionItem = new QTreeWidgetItem(yearItem); versionItem->setText(0, "版本: " + version); versionItem->setText(1, QString::number(data.ir_r)); versionItem->setText(2, QString::number(data.ir_t)); versionItem->setToolTip(1, QString("IR_R: %1\nIR_T: %2\nIRTS: %3") .arg(data.ir_r) .arg(data.ir_t) .arg(data.irts)); versionItem->setToolTip(2, versionItem->toolTip(1)); } } denomItem->setExpanded(true); } treeWidget->expandAll(); } 这个代码帮我修改一下逻辑,改为遍历到size以后,继续读取的时候,按照四行是一个面额的某个年份的四个面的值,此时如果遇到面额为10000000的记录就跳过这组,进入下一组,也就是从size后面跳过四行数据后开始读取我需要的数据并且按照面额从大到小、年限从大到小排序,然后在读取到最后一个面额的最后一个年份的这一组的第四行数据以后,就不继续往下读取了,判断是否是最后一个面额的最后一个年份的最后一行数据,可以根据后面还有没有面额来判断,如果超过三组数据也就是十二行数据都是空白的就不继续读取了
08-08
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值