数字转换、界面格式化和调试输出处理的是不同问题。转换要检查失败与范围,格式化要明确小数位和区域设置,日志则帮助观察程序状态。把三者写在同一段代码里时,也要避免重复声明局部变量。
以下使用 Qt 6 与 C++17,链接 Qt6::Core。
数字与字符串之间的转换
跳转到“数字与字符串之间的转换”QString::number(123) 得到十进制字符串。反向转换时,使用 toInt(&ok) 或 toDouble(&ok) 的成功标志:返回 0 不足以区别合法零与转换失败。还要按业务检查范围,例如端口、行数或频率不能只凭“能转成整数”就接受。QString 数值转换
QString 的这类数值解析采用 C 区域规则。面向使用本地小数分隔符的用户输入,明确使用合适的 QLocale,不要把逗号盲目替换成点,因为它也可能表示千位分隔符。QLocale 数值解析
格式化与调试的选择
跳转到“格式化与调试的选择”| 需求 | 接口 | 注意事项 |
|---|---|---|
| 将数值转成文本 | QString::number | 明确进制或浮点格式与精度 |
| 将值放进一句话 | QString::arg | %1、%2 等为占位符;数字格式参数影响展示 |
| 逐段构造文本 | QTextStream | 写入 QString 或设备;真正写文件还要检查设备与流状态 |
| 保留 C 风格格式 | QString::asprintf | 静态函数;可变参数必须与格式符匹配 |
| 观察状态 | qDebug()、qWarning() | 面向日志;默认会对字符串加引号、转义部分字符 |
旧代码的 output.sprintf(...) 不是 Qt 6 的可用成员接口。新代码通常用 arg 或 QTextStream;确需 C 风格格式时可用静态 QString::asprintf,但不能将外部输入直接作为格式字符串。QString 格式化、QTextStream、QDebug
arg(number, 0, 'f', 2) 中,0 表示不要求额外最小字段宽度,'f' 表示固定小数形式,2 表示显示两位小数。它会对显示结果舍入,不会改变原变量,也不会提高原浮点数的精度。默认的 QString::number(double) 精度也不保证任意 double 文本往返无损;需要往返时应明确精度和存储格式。
完整例子
跳转到“完整例子”程序保留 123、123.45678/987.65432 与 John/25 的原始例子,并检查合法零、失败、溢出以及本地化小数。
#include <QDebug>#include <QLocale>#include <QString>#include <QTextStream>#include <cassert>
int main() { const int number = 123; const QString text = QString::number(number); assert(text == "123");
bool ok = false; const int parsed = text.toInt(&ok); assert(ok && parsed == 123); const int zero = QStringLiteral("0").toInt(&ok); assert(ok && zero == 0); const int invalid = QStringLiteral("not a number").toInt(&ok); assert(!ok && invalid == 0); const int overflow = QStringLiteral("999999999999999999999").toInt(&ok); assert(!ok && overflow == 0);
const double decimal = QStringLiteral("1.5").toDouble(&ok); assert(ok && decimal == 1.5); (void)QStringLiteral("1,5").toDouble(&ok); assert(!ok); const QLocale german(QLocale::German, QLocale::Germany); const double localized = german.toDouble(QStringLiteral("1,5"), &ok); assert(ok && localized == 1.5);
const double number1 = 123.45678; const double number2 = 987.65432; const QString formatted = QStringLiteral( "Number1 with 2 decimal places: %1, Number2 with 2 decimal places: %2") .arg(number1, 0, 'f', 2).arg(number2, 0, 'f', 2); assert(formatted == "Number1 with 2 decimal places: 123.46, " "Number2 with 2 decimal places: 987.65");
const int age = 25; const QString name = QStringLiteral("John"); const QString withArg = QStringLiteral("Name: %1, Age: %2").arg(name).arg(age); QString withStream; { QTextStream stream(&withStream); stream << "Name: " << name << ", Age: " << age; } const QString withPrintf = QString::asprintf("Name: %s, Age: %d", "John", age); assert(withArg == "Name: John, Age: 25"); assert(withStream == withArg && withPrintf == withArg);
qDebug() << "Number:" << number << "String:" << text; qDebug().noquote() << formatted; qDebug().noquote() << withArg;}日志中的 noquote() 适合阅读已经组织好的文本;它不会替你清理文本里的换行,也不能作为可靠的网络协议或文件格式。需要保留结构的输出,应先定义字段与编码,再使用对应的序列化接口。
更多运行时类型转换见 QVariant 与 QVariantMap。文件输入的边界检查见 文件校验。