5.1 printf()函数详解

C语言学习栏目目录

目录

printf()函数使用

printf()的转换说明修饰符

转换说明的意义


printf()函数和scanf()函数能让用户可以与程序交流,它们是输入/输出函数,或简称为I/O函数。它们不仅是C语言中的I/O函数,而且是最多才多艺的函数。过去,这些函数和C库的一些其他函数一样,并不是C语言定义的一部分。最初,C把输入/输出的实现留给了编译器的作者,这样可以针对特殊的机器更好地匹配输入/输出。后来,考虑到兼容性的问题,各编译器都提供不同版本的printf()和scanf()。尽管如此,各版本之间偶尔有一些差异。C90 和C99 标准规定了这些函数的标准版本,本书亦遵循这一标准。虽然printf()是输出函数,scanf()是输入函数,但是它们的工作原理几乎相同。两个函数都使用格式字符串和参数列表。我们先介绍printf(),再介绍scanf()。

    请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用%d,打印字符时使用%c。这些符号被称为转换说明(conversion specification),它们指定了如何把数据转换成可显示的形式。我们先列出ANSI C标准为printf()提供的转换说明,然后再示范如何使用一些较常见的转换说明。下表列出了一些转换说明和各自对应的输出类型。

printf()函数使用

/************************************************************************
功能:演示printf()函数
************************************************************************/

#include <stdio.h>
#define PI 3.141593
int main(void)
{
    int number = 7;
    float litre = 12.75;
    int cost = 7800;
    printf(" %d 个人喝了 %f 升啤酒s.\n", number, litre);
    printf("圆周率PI为: %f.\n", PI);
    printf("大佬一个月的工资为:\n");
    printf("%c%d\n", '$', 2 * cost);
    system("pause");
    return 0;
}

该程序的输出如下:

The 7 contestants ate 12.750000 berry pies.
The value of pi is 3.141593.
Farewell! thou art too dear for my possessing,
$15600
请按任意键继续. . .

这是printf()函数的格式:printf( 格式字符串, 待打印项1, 待打印项2,...);

待打印项1、待打印项2等都是要打印的项。它们可以是变量、常量,甚至是在打印之前先要计算的表达式。前面提到过,格式字符串应包含每个待打印项对应的转换说明。例如,考虑下面的语句:

	printf(" %d 个人喝了 %f 升啤酒s.\n", number, litre);

格式字符串是双引号括起来的内容。上面语句的格式字符串包含了两个待打印项number和litre对应的两个转换说明。下图演示了printf()语句的另一个例子。

警告:格式字符串中的转换说明一定要与后面的每个项相匹配,若忘记这个基本要求会导致严重的后果。千万别写成下面这样:

printf("The score was Squids %d, Slugs %d.\n", score1);

这里,第2个%d没有对应任何项。系统不同,导致的结果也不同。不过,出现这种问题最好的状况是得到无意义的值。如果只打印短语或句子,就不需要使用任何转换说明。如果只打印数据,也不用加入说明文字。

由于 printf()函数使用%符号来标识转换说明,因此打印%符号就成了个问题。如果单独使用一个%符号,编译器会认为漏掉了一个转换字符。解决方法很简单,使用两个%符号就行了:

pc = 2*6;
printf("Only %d%% of Sally's gribbles were edible.\n", pc);

下面是输出结果:

Only 12% of Sally's gribbles were edible.

printf()的转换说明修饰符

在%和转换字符之间插入修饰符可修饰基本的转换说明。表4.4和表4.5列出可作为修饰符的合法字符。如果要插入多个字符,其书写顺序应该与表4.4中列出的顺序相同。不是所有的组合都可行。表中有些字符是C99新增的,如果编译器不支持C99,则可能不支持表中的所有项

注意 类型可移植性sizeof 运算符以字节为单位返回类型或值的大小。这应该是某种形式的整数,但是标准只规定了该值是无符号整数。在不同的实现中,它可以是unsigned int、unsigned long甚至是unsigned long long。因此,如果要用printf()函数显示sizeof表达式,根据不同系统,可能使用%u、%lu或%llu。这意味着要查找你当前系统的用法,如果把程序移植到不同的系统还要进行修改。鉴于此,  C提供了可移植性更好的类型。首先,stddef.h头文件(在包含stdio.h头文件时已包含其中)把size_t定义成系统使用sizeof返回的类型,这被称为底层类型(underlying type)。其次,printf()使用z修饰符表示打印相应的类型。同样,C还定义了ptrdiff_t类型和t修饰符来表示系统使用的两个地址差值的底层有符号整数类型。

注意 float参数的转换

对于浮点类型,有用于double和long  double类型的转换说明,却没有float类型的。这是因为在K&R C中,表达式或参数中的float类型值会被自动转换成double类型。一般而言,ANSI  C不会把float自动转换成double。然而,为保护大量假设float类型的参数被自动转换成double的现有程序,printf()函数中所有float类型的参数(对未使用显式原型的所有C函数都有效)仍自动转换成double类型。因此,无论是K&R C还是ANSI C,都没有显示float类型值专用的转换说明。

使用修饰符和标记的示例
接下来,用程序示例演示如何使用这些修饰符和标记。先来看看字段宽度在打印整数时的效果。考虑程序清单中的程序。

/************************************************************************
功能:演示printf()函数
************************************************************************/

#include <stdio.h>
#define PAGES 959

int main(void) 
{

	printf("*%d*\n", PAGES);
	printf("*%2d*\n", PAGES);
	printf("*%10d*\n", PAGES);
	printf("*%-10d*\n", PAGES);
	system("pause");
	return 0;
}

程序清单通过4种不同的转换说明把相同的值打印了4次。程序中使用星号(*)标出每个字段的开始和结束。其输出结果如下所示:

*959*
*959*
*       959*
*959       *
请按任意键继续. . .

第1个转换说明%d不带任何修饰符,其对应的输出结果与带整数字段宽度的转换说明的输出结果相同。在默认情况下,没有任何修饰符的转换说明,就是这样的打印结果。第2个转换说明是%2d,其对应的输出结果应该是 2 字段宽度。因为待打印的整数有 3 位数字,所以字段宽度自动扩大以符合整数的长度。第  3个转换说明是%10d,其对应的输出结果有10个空格宽度,实际上在两个星号之间有7个空格和3位数字,并且数字位于字段的右侧。最后一个转换说明是%-10d,其对应的输出结果同样是  10  个空格宽度,-标记说明打印的数字位于字段的左侧。熟悉它们的用法后,能很好地控制输出格式。试着改变PAGES的值,看看编译器如何打印不同位数的数字。

浮点型格式

请输入、编译并运行程序清单中的程序

//程序跟上面程序清单放在用一个文件中,所以没有放预处理器,完整程序可以在文章末尾下载源码,免费

int main(void) 
{
	const double RENT = 3852.99;   // const变量
	printf("*%f*\n", RENT);
	printf("*%e*\n", RENT);
	printf("*%4.2f*\n", RENT);
	printf("*%3.1f*\n", RENT);
	printf("*%10.3f*\n", RENT);
	printf("*%10.3E*\n", RENT);
	printf("*%+4.2f*\n", RENT);
	printf("*%010.2f*\n", RENT);
	system("pause");
	return 0;
}

该程序中使用了const关键字,限定变量为只读。该程序的输出如下:

*3852.990000*
*3.852990e+03*
*3852.99*
*3853.0*
*  3852.990*
* 3.853E+03*
*+3852.99*
*0003852.99*
请按任意键继续. . .

本例的第1个转换说明是%f。在这种情况下,字段宽度和小数点后面的位数均为系统默认设置,即字段宽度是容纳带打印数字所需的位数和小数点后打印6位数字。第2个转换说明是%e。默认情况下,编译器在小数点的左侧打印1个数字,在小数点的右侧打印6个数字。这样打印的数字太多!解决方案是指定小数点右侧显示的位数,程序中接下来的 4 个例子就是这样做的。请注意,第4个和第6个例子对输出结果进行了四舍五入。另外,第6个例子用E代替了e。第7个转换说明中包含了+标记,这使得打印的值前面多了一个代数符号(+)。0标记使得打印的值前面以0填充以满足字段要求。注意,转换说明%010.2f的第1个0是标记,句点(.)之前、标记之后的数字(本例为10)是指定的字段宽度。尝试修改RENT的值,看看编译器如何打印不同大小的值。

 转换说明的意义

下面深入探讨一下转换说明的意义。转换说明把以二进制格式储存在计算机中的值转换成一系列字符(字符串)以便于显示。例如,数字76在计算机内部的存储格式是二进制数01001100。%d转换说明将其转换成字符7和6,并显示为76;%x转换说明把相同的值(01001100)转换成十六进制记数法4c;%c转换说明把01001100转换成字符L。转换(conversion)可能会误导读者认为原始值被转替换成转换后的值。实际上,转换说明是翻译说明,%d的意思是“把给定的值翻译成十进制整数文本并打印出来”。

打印较长的字符串
有时,printf()语句太长,在屏幕上不方便阅读。如果空白(空格、制表符、换行符)仅用于分隔不同的部分,C 编译器会忽略它们。因此,一条语句可以写成多行,只需在不同部分之间输入空白即可。

 

源码下载

  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值