欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

5.1 printf()函数详解

程序员文章站 2022-05-12 16:32:56
...

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()提供的转换说明,然后再示范如何使用一些较常见的转换说明。下表列出了一些转换说明和各自对应的输出类型。

5.1 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()语句的另一个例子。

5.1 printf()函数详解

5.1 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,则可能不支持表中的所有项

5.1 printf()函数详解

注意 类型可移植性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类型值专用的转换说明。

5.1 printf()函数详解

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

/************************************************************************
功能:演示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 编译器会忽略它们。因此,一条语句可以写成多行,只需在不同部分之间输入空白即可。

 

源码下载

相关标签: C语言学习