【写在前面】
最近在看《深入理解计算机系统 第二版》简称 CSAPP,这本书我是极力推荐的,深度和广度都有 ( 而且讲解得非常仔细 )。
然后自己是第二遍看了 ( 之前看的第一版,第二版有不少新东西 ),里面的题也是一直跟着做的,就顺手写了几个小函数来方便做题。
因为书里的一些题目很多时候需要查看变量的 【位级表示 / 字节表示 / 内存地址】,然而对简单打印出来的格式很不满意,所以想着 Qt 中比较好用的 QTextStream 来进行格式化输出 ( QDebug 也可以,但还不够方便)。
所以这里就简单分享一些小技巧吧。
【正文开始】
先来看代码:
#include <QCoreApplication>
#include <QDebug>void show_addr(void *in, size_t size)
{QString result;QTextStream stream(&result);stream.setFieldWidth(12);stream.setFieldAlignment(QTextStream::AlignLeft);stream << "address: ";stream.setFieldAlignment(QTextStream::AlignRight);for (size_t i = 0; i < size; i++) {stream << static_cast<uchar *>(in) + i;}qDebug().noquote() << result;
}void show_bits(void *in, size_t size)
{QString result;QTextStream stream(&result);stream.setFieldWidth(12);stream.setFieldAlignment(QTextStream::AlignLeft);stream << "bits: ";stream.setFieldAlignment(QTextStream::AlignRight);for (size_t i = 0; i < size; i++) {uchar uc = static_cast<uchar *>(in)[i];stream << QString::number(uc, 2).rightJustified(8, '0');}qDebug().noquote() << result;
}void show_bytes(void *in, size_t size)
{QString result;QTextStream stream(&result);stream.setFieldWidth(12);stream.setFieldAlignment(QTextStream::AlignLeft);stream << "bytes: ";stream.setFieldAlignment(QTextStream::AlignRight);for (size_t i = 0; i < size; i++) {uchar uc = static_cast<uchar *>(in)[i];stream << QString::number(uc, 16).rightJustified(2, '0');}qDebug().noquote() << result;
}int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);uint64_t mx = static_cast<uint64_t>(-1);show_bits(&mx, sizeof(mx));show_bytes(&mx, sizeof(mx));show_addr(&mx, sizeof(mx));return a.exec();
}
输出如下 ( 注意: 我的电脑是小端字节序 ):
可以看到,格式化后的输出顺眼多了 。
其中,主要依靠这几个函数完成:
QString QString::number(long n, int base = 10):
将数数字(整数、浮点数、有符号、无符号等)转换为 QString 类型,而基数可以简单的理解为进制。
QString QString::rightJustified(int width, QChar fill = QLatin1Char(' '), bool truncate = false) const:
返回一个 size() 宽度的字符串,其中包含填充字符,后跟该字符串。 例如:
QString s =“apple”;
QString t = s.rightJustified(8,'.'); // t ==“ ...apple”
如果 truncate 为 false 并且字符串的 size() 大于 width,则返回的字符串是该字符串的副本。
如果 truncate 为 true,并且字符串的 size() 大于 width,则结果字符串在位置 width 处被截断。
QString str = “Pineapple”;
str = str.rightJustified(5,'.',true); // str ==“Pinea”
void QTextStream::setFieldWidth(int width):
将当前字段的宽度设置为 width 。 如果 width 为 0 ( 默认值 ),则字段宽度等于生成的文本的长度。
注意:字段宽度适用于调用此函数后附加到此流的每个元素 ( 例如,它也填充 endl )。 此行为不同于 STL 中的类似类,在 STL 中,字段宽度仅适用于下一个元素。
QTextStream :: setFieldAlignment(QTextStream :: FieldAlignment mode):
将字段对齐方式设置为 mode。 与 setFieldWidth() 一起使用时,此函数允许您生成格式化的输出,其中文本左对齐,右对齐或居中对齐。
void QTextStream::setPadChar(QChar ch) :
将填充字符设置为 ch。 默认值为 ASCII 空格字符 (' ') 或 QChar(0x20)。 生成文本时,此字符用于填充字段中的空格,即超过 fieldWidth() 的部分。
【结语】
实际上,另一种方法是使用 QTextStream 的 bin() / hex() / setIntegerBase() 也能达到同样的效果,但是会麻烦许多。
最后再推荐一次《深入理解计算机系统 第二版》,话说第二版题目的答案都详细很多了,很赞 ?。