C语言的格式化输出

最近在复习C语言时发现自己对C语言某些格式化输出的规则还有些模糊,于是就重新总结学习了一下,果然温故知新,还是值得说一下滴。(其实就是手痒了想写点简单的内容,不过你可以先看一下接下来的这个小demo,看看关于格式化的东西都还记得不,检验一下自己的C语言基础怎么样)

检验一下自己

先展示一个有趣的小进度条demo:

效果就是一个加载进度条的动画

说明:包括进度条、加载百分比、以及一个小小的加载轮,由“ -\|/ ”组成

#include<stdio.h>
#include<windows.h>
#include<string>

#define SIZE 101
#define FLAG '='

int main() {
	char buffer[SIZE];
	memset(buffer, 0, sizeof(buffer));
	int rate = 0;
	const char* loadSign = "-\\|/";
	int len = strlen(loadSign);
	while(rate<=100){
		printf("[%-100s][%d%%][%c]\r", buffer, rate, loadSign[rate % len]);
		buffer[rate] = FLAG;
		Sleep(100);
		rate++;
	}
	printf("\n");
	return 0;
}

代码就不细说了,相信大家都能看懂。

我要讲的主要是这行代码,如果接下来的问题你都清楚,那你可以退出了,你的基础很牢固:

printf("[%-100s][%d%%][%c]\r", buffer, rate, loadSign[rate % len]);
memset(buffer, 0, sizeof(buffer));

问题:

1)%-100s 是在干什么?“ - ” 和数字100是分别什么效果?

2)%% 是什么?

3)\r 是什么?

4)为什么要用memset函数将所有单位字节设置为0?(你不会忘了啥是memset吧???)

5)以及如果你学习了Linux系统操作,这段代码还能运行出正常效果吗?(涉及缓冲区问题)

格式修饰符

在%和格式符之间的符号叫做格式修饰符

%-100s中的-100就是格式修饰符,格式修饰符的意义在于对输出字符的宽度控制和精度控制

宽度控制(都是很简单的例子,没有图例,自己在编译器上输出试验)

        1)如%5d,输出的内容至少5个字符宽,不足5个字符编译器会自动用空格填充,但是输出的内容是右对齐的!!

        2)如%-5d,输出5个字符宽,与上面一样,唯一区别在于输出内容是左对齐的!

        3)如%05d,宽度仍然是5,但不是空格补齐,而是字符0补齐的!

精度控制

        1)如%.2f,浮点数保留两位小数

        2)如%.2s,输出字符串的前两个字符

现在问题1)的答案已经可以得出了 %-100s 的输出效果:表示左对齐一个字符串,并保证占用100个字符宽,字符串不足100个字符宽的空格自动补齐。

转义字符(常见)

在进行字符输出时,有些字符是不能直接用的,如“ \ ”,还有些是字符表意无法直接表达的,如换行,都需要转义字符进行表示。

转义字符含义
\n换行
\r回车
\\反斜杠
\'单引号
\''双引号
\t水平制表符
%%百分号
\0空字符

问题2)、3)、4)解决,注意这里的\r回车的含义不是键盘上的回车键,而是光标回到所在行的开头

问题4)单独说一下,因为这行代码将buffer数组的所有字节都设置为0(即空字符'\0'),将100个字符宽的字符串设置为空,以便进度条的填充。

问题5):在Linux上这段代码的运行效果

这里就要引出缓冲区的概念了:​​在C语言中,缓冲区(Buffer)​​是用于临时存储输入/输出数据的内存区域,目的是减少频繁的系统调用(如writeread),提高I/O效率。

简单来说,windows的输出是无缓冲输出的,所以这段代码会直接输出到控制台。而在Linux中的输出属于行缓冲,只有碰到换行符才会输出到终端上。而demo中的输出代码结尾是 \r 是回车符,所以Linux的输出内容会停滞在缓冲区中直至程序结束或手动刷新缓冲区,那么运行效果就是什么也不显示,因为程序结束时终端也随之关闭。

解决方法:手动刷新缓冲区 在printf()代码的下一行添加 fflush(stdout) ,即每打印一次就刷新一次缓冲区,使每次打印都能输出到终端上即可。

#include<stdio.h>
#include<unistd.h>
#include<string.h>

#define SIZE 101
#define FLAG '='

//进度条demo
int main(){
    int rate = 0;
    char buffer[SIZE];
    memset(buffer,0,sizeof(buffer));
    const char* l = "-\\|/";
    int len = strlen(l);
    while(rate<=100){
        printf("[%-100s][%d%%][%c]\r",buffer,rate,l[rate%len]);
        fflush(stdout);
        buffer[rate]=FLAG;
        usleep(100000);
        rate++;
    }
    printf("\n");
    return 0;
}

本篇的内容到这就结束了,嘿嘿,虽然内容简单,但我还是想狡辩一下。

我们在学习时的收获都是具有滞后性的,每次初学新内容都会忘得很快,所以时不时的复习很重要,就算是简单的东西在复习后也会有很深的收获,我想分享的不止是简单的知识,更是这种复习收获时带来的快乐。希望各位同仁多多努力,祝我们都有美好的前程^(* ̄(oo) ̄)^。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值