编程技能:格式化打印05,格式控制符

news2025/7/22 22:30:34

专栏导航

本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。

(一)WIn32 专栏导航

上一篇:编程技能:格式化打印04,sprintf

回到目录

下一篇:无

(二)MFC 专栏导航

上一篇:编程技能:格式化打印04,sprintf

回到目录

下一篇:无

本节前言

在前几节,我们讲解了 vsprintf,printf 与 sprintf 函数。如果,这几节,你学得很好,那么,对于格式控制符,格式字符串等等的概念,你就会有一定的了解了。同时,对于可变参数啥的,你也会有一定的了解。你也会了解到 printf 与 vsprintf 的互动机制,了解到 sprintf 与 vsprintf 的互动机制。

以上的内容,我认为,都是很重要的。

然而,在讲解以上几节内容的时候,我并未对格式控制符详细展开。本节,我也并不打算详细地讲解格式控制符的每一个知识点。然而,我还是想要多讲解一点关于格式控制符的知识。

本节,将作为格式化打印版块儿的最后一节。希望大家能够学好本节。

本节结束了以后,我们将会进入正式的 Windows 编程知识的讲解。无论你是进入 Win32 知识的学习,还是进入 MFC 知识的学习。

我们开始本节的讲解。

一.    什么是格式控制符?

格式控制符,是我在我的专栏里面所采用的概念。通行的术语是什么,我记不清了。此刻,我也不想去专门查阅这个东西。

在我的专栏里,我将 printf,sprintf 函数里面的 %d,%c,%f,%s 等等的东西,叫做格式控制符

例如,代码【printf("a + b = %d\n", a + b);】里面,%d 便是格式控制符。%d 表明,在输出打印的时候,%d 所在的位置,应该是一个 int 型的数据。

在基本的 C 语言学习里面,一般地,我们只是在使用着格式控制符,而并未对其进行专门的学习。

格式控制符,除了基本的 %d,%c,%s,%f 等等的东西以外,其实还包括其他的一些个有趣的东西的。

在本节,我打算讲解与浮点数无关的一些个格式控制符的知识。因为,水平所限,让我讲浮点型的,此时我也讲不了。

在格式控制符里面,比较简单的组成,是左边一个 %,右边一个 d,c,s 等等的字符。

除了这样的简单组成以外,其实格式控制符还可以有其他的部分。

与浮点数无关的格式控制符,还可以包含有许多的字段与标志。可以包含的标志有,填零标志,符号标志,正号标志,空格标志,特殊显示标志,左对齐标志,大小写标志。可以包含的字段有,宽度字段,精度字段。

接下来,我来尝试着讲解一下这些个字段与标志。为了方便讲解,我首先来讲解字段,然后再去讲解标志。

二.    宽度字段

字段,我初次接触这个概念,是在学习数据库的时候。字段,英文为 field 。对于 field,有的人将其翻译为【字段】,有的人将其翻译为【域】。所以,【宽度字段】,有的人也将其称作【宽度域】。其它的,涉及【字段】这个概念的,你都可以将【某某字段】其叫做【某某域】。

我下定义的能力,有时候并不强。所以,对于宽度字段这个概念,我用举例子的方式来加以说明。

比如,代码【printf("小丽的口袋里有%d块钱", 37);】,这段代码里,不包括宽度字段。我们给它加上一个宽度字段。加上宽度字段之后,代码为【printf("小丽的口袋里有%6d块钱", 37);】。

看到了没?在 % 与 d 之间,加上了一个数字 6,这个数字 6,便是属于宽度字段。当然了,你也可以不使用 6 这个数,你也可以使用 9,7,12 等等的整数。总之呢,在 % 和 d 之间,直接加上一个整数,中间不含空格,这个所加的整数,便是宽度字段。

它的执行效果,我们可以给出一个示例代码。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 37);
	printf("小丽的口袋里有%3d块钱\n", 37);
	printf("小丽的口袋里有%6d块钱\n", 37);
	printf("小丽的口袋里有%9d块钱\n", 37);
	return 0;
}

运行结果如下。

图1

大家看到了吧?

在不加宽度字段的时候,%d 的位置,在打印输出时,直接被转换为【37】这个整数。【37】这个这个数,本身占用的是 2 个字符的宽度。

在 %3d 里面,转换成的整数依旧是 37,它本身依旧是占用 2 个字符的宽度。然而,却在 37 这个数的左边,加了一个空格。一个空格占用的是 1 个字符的宽度。加上去的占用 1 个字符宽度的 1 个空格,与占用 2 个字符宽度的 37,合起来,一共是占用了 3 个字符宽度。

在 %6d 里面,转换成的整数依旧是 37,它本身依旧是占用 2 个字符的宽度。然而,却在 37 这个数的左边,加了 4 个空格。一个空格占用的是 1 个字符的宽度。加上去的占用 4 个字符宽度的 4 个空格,与占用 2 个字符宽度的 37,合起来,一共是占用了 6 个字符宽度。

在 %9d 里面,转换成的整数依旧是 37,它本身依旧是占用 2 个字符的宽度。然而,却在 37 这个数的左边,加了 7 个空格。一个空格占用的是 1 个字符的宽度。加上去的占用 7 个字符宽度的 7 个空格,与占用 2 个字符宽度的 37,合起来,一共是占用了 9 个字符宽度。

%3d,使得转换后的东西,占用了 3 个字符的宽度。%6d,使得转换后的东西,占用了 6 个字符的宽度。%9d,使得转换后的东西,占用了 9 个字符的宽度。

原本,我们要替换的数,是37,它只占用 2 个字符的宽度。那么,对于 %3d,在数字 37 所占用的 2 个字符宽度之外,需要添加 1 个空格。对于 %6d,在数字 37 所占用的 2 个字符宽度之外,需要添加 4 个空格。对于 %9d,在数字 37 所占用的 2 个字符宽度之外,需要添加 7 个空格。

这样一来,对于宽度字段,以及所添加的空格数的关系,大家应该就能够明白了吧?

宽度字段,是建议转换后的东西,一共占用多少个字符的宽度。原本的数字,若不够这个宽度的话,默认地,会填上空格,以凑成宽度字段所要求的宽度。

不过,在以上的例子中,我们给出的宽度,是大于数字 37 本身所占用的 2 个字符的宽度值的。如果,我们给出的,是 %1d,会如何呢?

宽度字段的值 1,小于数字 37 本身的宽度值 2,那么,结果是,37 这个数字正常输出,%1d 中的宽度字段 1 不起作用。

同理地,对于【printf("%3d", 123456);】,由于 123456 占用的字符宽度值为 6,而 %3d 中的宽度字段值为 3,3 小于 6,所以呢,宽度字段值 3 不起作用,实际输出的时候,123456 依旧会正常地输出。

但是呢,如果是【printf("%9d", 123456);】,123456 这个数占用的字符宽度值为 6,而 %9d 中的宽度字段值为 9,由于 9 大于 6,所以,实际打印输出的时候,%9d 的位置,被转换后的内容,真的会占用 9 个字符的宽度的。此时,由于 123456 这个数已经占用了 6 个字符,所以呢,为了凑成 9 个字符的宽度,只需要再添加 3 个空格就好了。

到了这里,对于宽度字段,大家应该是懂了吧?

三.    精度字段

我们还是以小丽口袋里的钱来说事。我们给出如下的代码。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 37);
	printf("小丽的口袋里有%.3d块钱\n", 37);
	printf("小丽的口袋里有%.6d块钱\n", 37);
	printf("小丽的口袋里有%.9d块钱\n", 37);
	return 0;
}

运行结果如下。

图2

看懂了没?在 % 与 d 之间,加上一个【.x】,其中的 x 为一个整数,这个【.x】,就是精度字段。【x】是几,就表示说,让转换后的整数占用多少个字符精度,若是整数本身的宽度不足精度数的,则补 0 。

%.3d 是建议,转换后的数字,要占用 3 个字符精度,而待转换的数字 37 只占用 2 个字符宽度,所以呢,左边补上 1 个 0 。

%.6d 是建议,转换后的数字,要占用 6 个字符精度,而待转换的数字 37 只占用 2 个字符宽度,所以呢,左边补上 4 个 0 。

%.9d 是建议,转换后的数字,要占用 9 个字符精度,而待转换的数字 37 只占用 2 个字符宽度,所以呢,左边补上 7 个 0 。

那么,如果精度数小于待转换数字本身占用的字符宽度,这会如何呢?与宽度字段类似,此时,精度字段不起作用,待转换数字会正常地输出,相当于单纯的 %d,精度字段会被忽略掉。

例如,对于【printf("%.3d", 123456);】,由于 123456 占用的字符宽度值为 6,而 %.3d 中的精度字段值为 3,3 小于 6,所以呢,精度字段值 3 不起作用,实际输出的时候,123456 依旧会正常地输出,相当于单纯的 %d,精度字段被忽略掉。

四.    宽度字段与精度字段连用

啊,我给出一段代码。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 137);
	printf("小丽的口袋里有%6.5d块钱\n", 137);
	printf("小丽的口袋里有%9.6d块钱\n", 137);
	printf("小丽的口袋里有%7.4d块钱\n", 137);
	return 0;
}

运行结果如下。

图3

在 %d 一行,数字 137 正常输出。

在 %9.6d 一行,要求精度值为 6,而数字 137 占用 3 个字符宽度,所以呢,数字 137 左边补上了 3 个 0 。最后呢,在精度值为 6 的条件下,宽度字段值为 9,为了凑齐整个的宽度值 9,还需要补上 3 个空格。

在 %7.4d 一行,要求精度值为 4,而数字 137 占用 3 个字符宽度,所以呢,数字 137 左边补上了 1 个 0 。最后呢,在精度值为 4 的条件下,宽度字段值为 7,为了凑齐整个的宽度值 7,还需要补上 3 个空格。

精度值决定了这个数显示为多少个数位,不足精度数的话,就在左边补 0 。宽度字段值,则是说,精度值小于宽度值的话,就补上空格。

到了这里,宽度字段与精度字段,我大体上就算是讲完了。

接下来,我们来讲解各种标志。

五.    符号标志

符号标志,一般来讲,在 %d 格式控制符里面,自动包含了符号标志。也就是说,若某个整数是一个负整数,则会在 %d 输出时,在数字前面加上负号【-】,这就是符号标志的意义。而对于 %c,%x,%X,%s,则不存在符号标志。

%d,用于输出带符号整数。%u,则是用于输出无符号整数。%d,会包含有符号标志,而 %u,则是不含符号标志。因为,无符号数,其实就是自然数,它只包含 0 和 正整数,不包含负整数。

我的建议是,对于符号标志,了解一下就可以了。

六.    正号标志

它的意思是,若是 %d 输出的整数是一个正数或 0,则会在前面加上一个正号。

案例代码如下。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有 %d 块钱\n", 37);
	printf("小丽的口袋里有 %+d 块钱\n", 37);
	return 0;
}

运行结果如下。

图4

由于 37 是一个正整数,所以,在 %+d 格式控制符的输出里面,输出的,是【+37】。

七.    左对齐标志

左对齐标志,由负号【-】来标识,需要结合着宽度字段来使用。

默认的情况下,%d,%c,%s 等等的格式控制符所转换出来的东西,在加上了宽度字段以后,空格在左,而有效字符在右边。所以,输出内容默认的对齐方式为右对齐。

然而,若是在与宽度字段连用的时候,加上了左对齐标志【-】,则会让有效的输出字符在左边,补充宽度的空格在右边。

比如,不加左对齐标志的 %6d 所对应的添加了左对齐标志的格式控制符为 %-6d。不加左对齐标志的 %9d 所对应的添加了左对齐标志的格式控制符为 %-9d 。

案例代码如下。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 137);
	printf("小丽的口袋里有%6d块钱\n", 137);
	printf("小丽的口袋里有%-6d块钱\n", 137);
	return 0;
}

运行结果如下。

图5

八.    空格标志

空格标志,由空格来标识。需要与 %d 一类的格式连用。例如,【% d】。

空格标志的意思是,当符号标志开启,也就是使用了 %d 一类的带符号整数的格式控制符的时候,若是整数大于或等于 0,则会在整数前面加上一个空格。

案例代码如下。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 137);
	printf("小丽的口袋里有% d块钱\n", 137);
	
	return 0;
}

运行结果如下。

图6

九.    填零标志

填零标志由数字 0 来标识,一般与宽度字段连用。例如,不加填零标志的 %6d 所对应的添加了填零标志的格式控制符为 %06d 。

案例代码如下。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 137);
	printf("小丽的口袋里有%06d块钱\n", 137);
	
	return 0;
}

运行结果如下。

图7

十.    大小写标志

大小写标志,只对十六进制有意义。使用 %x 的时候,自动添加小写标志。使用 %X 的时候,自动添加大写标志。

当显示 0x30AE 这样的,含有介于字母 A 到 F 之间的某一个十六进制符号的时候,若是使用了 %x,采用了小写标志,则会显示为 0x30ae 。若是使用了 %X,采用了大写标志,则会显示为 0x30AE 。

本条目,我就不给出案例代码了。

十一.    特殊显示标志

特殊显示标志,由井号【#】来标识,只对八进制与十六进制起作用。八进制的简单格式控制符为 %o,十六进制的简单格式控制符为 %x 或 %X 。若是添加了特殊显示标志,比如 %#o,%#x,或 %#X,则在打印输出时,会在八进制数前面加上一个 0,在十六进制数前面加上 0x 或 0X 。

案例代码如下。

#include <stdio.h>

int main(void)
{
	printf("小丽的口袋里有%d块钱\n", 137);
	printf("小丽的口袋里有%o块钱\n", 137);
	printf("小丽的口袋里有%#o块钱\n", 137);
	printf("小丽的口袋里有%x块钱\n", 137);
	printf("小丽的口袋里有%#x块钱\n", 137);
	printf("小丽的口袋里有%X块钱\n", 137);
	printf("小丽的口袋里有%#X块钱\n", 137);
	return 0;
}

运行结果如下。

图8

结束语

本节的内容很多,但是呢,难度应该是不大的。

关于格式控制符的内容,你还可以自己多去进行一些个尝试的。

总算是讲完了 Windows 编程的预备知识了。

预备知识的讲解,对我来讲,也是有些累的。

所以呢,接下来,我可能会休息几天。跟着本专栏学习的同学,可能需要略作等待了。

在我写作的当前,我暂时先不打算去讲解 Win32 知识,而是先去讲解 MFC 的知识。至于 Win32 知识什么时候讲,再说了。

反正,此刻,我是打算先去讲解 MFC 的。

下一节,我们就开始正式的 Windows 编程章节的讲解了。

专栏导航

本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。

(一)WIn32 专栏导航

上一篇:编程技能:格式化打印04,sprintf

回到目录

下一篇:无

(二)MFC 专栏导航

上一篇:编程技能:格式化打印04,sprintf

回到目录

下一篇:无

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2401443.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MPLAB X IDE ​软件安装与卸载

1、下载MPLAB X IDE V6.25 MPLAB X IDE | Microchip Technology 正常选Windows&#xff0c;点击Download&#xff0c;等待自动下载完成&#xff1b; MPLAB X IDE 一台电脑上可以安装多个版本&#xff1b; 2、安装MPLAB X IDE V6.25 右键以管理员运行&#xff1b;next; 勾选 I a…

windows编程实现文件拷贝

项目源码链接&#xff1a; 实现文件拷贝功能&#xff08;限制5GB大小&#xff09; 81c57de 周不才/cpp_linux study - Gitee.com 知识准备&#xff1a; 1.句柄 句柄是一个用于标识和引用系统资源&#xff08;如文件、窗口、进程、线程、位图等&#xff09;的值。它不是资…

[6-01-01].第12节:字节码文件内容 - 属性表集合

JVM学习大纲 二、属性表集合&#xff1a; 2.1.属性计数器&#xff1a; 2.2.属性表&#xff1a; 2.3.字节码文件组成5 -> 属性&#xff1a; 1.属性主要指的是类的属性&#xff0c;比如源码的文件名、内部类的列表等 2.4.字节码文件组成3 -> 字段&#xff1a; 1.字段中…

基于机器学习的水量智能调度研究

摘要&#xff1a;随着城市化进程的加速和水资源供需矛盾的日益突出&#xff0c;传统的水量调度模式因缺乏精准预测和动态调控能力&#xff0c;难以满足现代供水系统对高效性、稳定性和节能性的要求。本文针对供水系统中用水峰谷预测不准确、能耗高、供需失衡等核心问题&#xf…

深入浅出 Scrapy:打造高效、强大的 Python 网络爬虫

在数据为王的时代,高效获取网络信息是开发者必备的技能。今天我将为大家介绍 Python 爬虫领域的王者框架——Scrapy。无论你是数据工程师、分析师还是开发者,掌握 Scrapy 都能让你的数据采集效率提升数倍! 项目地址:https://github.com/scrapy/scrapy 官方文档:https://do…

贪心算法应用:带权任务间隔调度问题详解

贪心算法应用&#xff1a;带权任务间隔调度问题详解 贪心算法是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。带权任务间隔调度问题是贪心算法的一个经典应用场景。 问题定义…

用电脑控制keysight示波器

KEYSIGHT示波器HD304MSO性能 亮点&#xff1a; 体验 200 MHz 至 1 GHz 的带宽和 4 个模拟通道。与 12 位 ADC 相比&#xff0c;使用 14 位模数转换器 &#xff08;ADC&#xff09; 将垂直分辨率提高四倍。使用 10.1 英寸电容式触摸屏轻松查看和分析您的信号。捕获 50 μVRMS …

LLaMA-Factory - 批量推理(inference)的脚本

scripts/vllm_infer.py 是 LLaMA-Factory 团队用于批量推理&#xff08;inference&#xff09;的脚本&#xff0c;基于 vLLM 引擎&#xff0c;支持高效的并行推理。它可以对一个数据集批量生成模型输出&#xff0c;并保存为 JSONL 文件&#xff0c;适合大规模评测和自动化测试。…

【Elasticsearch】Elasticsearch 核心技术(二):映射

Elasticsearch 核心技术&#xff08;二&#xff09;&#xff1a;映射 1.什么是映射&#xff08;Mapping&#xff09;1.1 元字段&#xff08;Meta-Fields&#xff09;1.2 数据类型 vs 映射类型1.2.1 数据类型1.2.2 映射类型 2.实际运用案例案例 1&#xff1a;电商产品索引映射案…

【计算机网络】网络层协议

1. ICMP协议的介绍及应用 IP协议的助手 —— ICMP 协议 ping 是基于 ICMP 协议工作的&#xff0c;所以要明白 ping 的工作&#xff0c;首先我们先来熟悉 ICMP 协议。 ICMP 全称是 Internet Control Message Protocol&#xff0c;也就是互联网控制报文协议。 里面有个关键词 …

结构型设计模式之Proxy(代理)

结构型设计模式之Proxy&#xff08;代理&#xff09; 前言&#xff1a; 代理模式&#xff0c;aop环绕通知&#xff0c;动态代理&#xff0c;静态代理 都是代理的一种&#xff0c;这次主要是记录设计模式的代理demo案例&#xff0c;详情请看其他笔记。 1&#xff09;意图 为其…

案例分享--汽车制动卡钳DIC测量

制动系统是汽车的主要组成部分&#xff0c;是汽车的主要安全部件之一。随着车辆性能的不断提高&#xff0c;车速不断提升&#xff0c;对车辆的制动系统也随之提出了更高要求&#xff0c;因此了解车辆制动系统中每个部件的动态行为成为了制动系统优化的主要途径&#xff0c;同时…

Redis Set集合命令、内部编码及应用场景(详细)

文章目录 前言普通命令SADDSMEMBERSSISMEMBERSCARDSPOPSMOVESREM 集合间操作SINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令小结内部编码使用场景 前言 集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中 1&#xff09;元…

C++算法动态规划1

DP定义&#xff1a; 动态规划是分治思想的延申&#xff0c;通俗一点来说就是大事化小&#xff0c;小事化无的艺术。 在将大问题化解为小问题的分治过程中&#xff0c;保存对这些小问题已经处理好的结果&#xff0c;并供后面处理更大规模的问题时直接使用这些结果。 动态规划具…

KaiwuDB在边缘计算领域的应用与优势

KaiwuDB 在边缘计算场景中主要应用于 工业物联网&#xff08;IIoT&#xff09;、智能电网、车联网 等领域&#xff0c;通过其分布式多模架构和轻量化设计&#xff0c;在边缘侧承担 数据实时处理、本地存储与协同分析 的核心作用。以下是具体案例和功能解析&#xff1a; 1. 典型…

鸿蒙开发List滑动每项标题切换悬停

鸿蒙开发List滑动每项标题切换悬停 鸿蒙List滑动每项标题切换悬停&#xff0c;功能也很常见 一、效果图&#xff1a; 二、思路&#xff1a; ListItemGroup({ header: this.itemHead(secondClassify, index) }) 三、关键代码&#xff1a; build() {Column() {List() {ListIt…

ubuntu开机自动挂载windows下的硬盘

我是ubuntu和windows的双系统开发&#xff0c;在ubuntu下如果想要访问windows的硬盘&#xff0c;需要手动点击硬盘进行挂载&#xff0c;这个硬盘我每次编译完都会使用&#xff0c;所以用下面的步骤简化操作&#xff0c;让系统每次开机后自动挂载。 第一步. 确定硬盘的设备标识…

使用 Golang `testing/quick` 包进行高效随机测试的实战指南

使用 Golang testing/quick 包进行高效随机测试的实战指南 Golang testing/quick 包概述testing/quick 包的功能和用途为什么选择 testing/quick 进行测试快速入门&#xff1a;基本用法导入 testing/quick 包基本使用示例&#xff1a;快速生成测试数据quick.Check 和 quick.Val…

32 C 语言字符处理函数详解:isalnum、isalpha、iscntrl、isprint、isgraph、ispunct、isspace

1 isalnum() 函数 1.1 函数原型 #include <ctype.h>int isalnum(int c); 1.2 功能说明 isalnum() 函数用于检查传入的整数参数是否为 ASCII 编码的字母或数字字符&#xff08;A - Z、a - z、0 - 9&#xff0c;对应 ASCII 值 65 - 90、97 - 122、48 - 57&#xff09;。…

Qt实现一个悬浮工具箱源码分享

一、效果展示 二、源码分享 hoverToolboxWidget.h #ifndef HOVERTOOLBOXWIDGET_H #define HOVERTOOLBOXWIDGET_H#include <QWidget> #include <QMouseEvent> #include <QPropertyAnimation> #include <QStyleOption> #include <QPainter>namespa…