1. 从一次调试经历说起:为什么你需要掌握进制转换?
几年前,我接手维护一个老旧的Qt项目,负责一个与硬件通信的模块。硬件工程师发来一份协议文档,里面密密麻麻全是十六进制数,比如 0x2ABC、0x00FF。我的任务是把这些数据在界面上清晰地显示出来,同时还要能接收用户输入的十进制数,转换成十六进制格式发送给设备。
刚开始,我天真地直接用 qDebug() << hexData; 输出,结果发现,如果数字是 0x0A,它打印出来就是个孤零零的 a,前面的 0 没了,这在协议里可是严格规定必须占满两个字节的。更头疼的是,用户输入 255,我怎么把它变成 00FF 再发出去?界面显示时,又怎么把收到的 2ABC 用大写字母 2ABC 显示,而日志里为了便于比对用小写 2abc?
那一阵子,我写了不少“手工”转换的代码,又笨又容易出错。直到我把 Qt 内置的进制转换和格式化输出功能摸透,才发现原来这些让人头疼的问题,Qt 早就提供了优雅又高效的解决方案。今天,我就把这些实战中积累的技巧分享给你,让你在遇到类似场景时,能游刃有余。
简单来说,在 Qt 开发中,尤其是涉及硬件通信、协议解析、数据加密、网络传输、日志记录时,进制转换和格式化输出就像螺丝刀和扳手,是基础但至关重要的工具。它们能确保数据以精确的格式呈现和交互,避免因格式错乱导致的隐蔽 Bug。
2. 核心武器:深入理解 QString::arg() 与 QString::number()
Qt 提供了多种方式来处理数字到字符串的转换,最常用、最灵活的两个方法是 QString::arg() 和 QString::number()。它们看似功能重叠,但在实际使用中各有侧重。
2.1 QString::arg():格式化输出的瑞士军刀
arg() 方法绝对是 Qt 格式化输出的王牌。它不仅能处理进制转换,还能轻松控制字段宽度、填充字符、对齐方式,功能非常强大。它的一个常用重载函数原型是这样的:
QString QString::arg(qlonglong a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char(' ')) const
参数解读:
a:要格式化的数字(整数类型)。fieldWidth:字段总宽度。如果转换后的字符串长度小于这个宽度,会用填充字符补足;如果大于,则按实际长度输出。设为0表示不限制宽度。base:进制基数。10 代表十进制,16 代表十六进制,8 代表八进制,2 代表二进制。这是实现进制转换的关键参数。fillChar:填充字符。当需要补足宽度时,用这个字符来填充。
让我们直接看代码,这比干巴巴的解释管用一百倍:
#include <QCoreApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
quint16 myNumber = 0x2ABC; // 十六进制数,十进制是10940
// 1. 最简单的十进制输出
QString decStr = QString("十进制: %1").arg(myNumber);
qDebug() << decStr; // 输出: 十进制: 10940
// 2. 十六进制输出,不补零
QString hexStrSimple = QString("十六进制(小写): %1").arg(myNumber, 0, 16);
qDebug() << hexStrSimple; // 输出: 十六进制(小写): 2abc
// 3. 十六进制输出,固定4位宽度,不足补0
QString hexStrPadded = QString("十六进制(补零): %1").arg(myNumber, 4, 16, QLatin1Char('0'));
qDebug() << hexStrPadded; // 输出: 十六进制(补零): 2abc
// 试试一个小的数
quint16 smallNum = 0x00F;
qDebug() << QString("小数字补零: %1").arg(smallNum, 4, 16, QLatin1Char('0')); // 输出: 小数字补零: 000f
// 4. 控制大小写:arg()本身输出小写,大写需要额外处理
QString hexLower = QString("%1").arg(myNumber, 4, 16, QLatin1Char('0')); // 小写
QString hexUpper = hexLower.toUpper(); // 转换为大写
qDebug() << "小写:" << hexLower << "大写:" << hexUpper; // 输出: 小写: "2abc" 大写: "2ABC"
// 5. 二进制输出,固定8位宽度
qDebug() << "二进制:" << QString("%1")


435

被折叠的 条评论
为什么被折叠?



