跳转到内容
新建笔记

Qt 字符串转换与调试:检查结果、格式化和日志

数字转换、界面格式化和调试输出处理的是不同问题。转换要检查失败与范围,格式化要明确小数位和区域设置,日志则帮助观察程序状态。把三者写在同一段代码里时,也要避免重复声明局部变量。

以下使用 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。文件输入的边界检查见 文件校验。