购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.5 标准I/O函数

一个好的程序应该会将运行的状态和执行的结果以信息的形式告知用户,甚至在某些情况下会要求得到用户的特定信息,这种与程序进行交流的行为就称为交互。我们把一个程序获取用户的信息称为程序的输入,将信息告知用户称为程序的输出,拥有这种功能的函数就称为I/O函数(Input/Output),即输入/输出函数。如果是通过控制台窗口来完成这些I/O操作的,即为标准I/O函数,C语言中有许多标准I/O函数,其中使用最广泛、功能最强大的是printf函数和scanf函数了。

2.5.1 再谈printf函数

在第1章的第一个C语言程序中使用了printf函数,程序通过这个函数在控制台的窗口上输出一行文本字符串。其实这只是printf函数最基本的用法,它还拥有更多强大的功能,值得我们进一步了解。

printf函数通常被称为“格式化打印函数”,它的第一个参数称为“格式化字符串”,在“格式化字符串”中可以使用“占位符”(或称转换说明符)把一些其他类型的数据镶嵌到文本字符串中进行打印输出。

不知大家在上学时有没有去图书馆抢座位的经历呢?先让某个腿快的同学跑去图书馆,找到空的座位,就在上面放一本书或一个文具盒,表示这个座位已经有主人了,直到同学来了,再把东西收起来,然后坐到座位上。“占位符”与占座非常类似,我们可以在“格式化字符串”的某个位置放一个“占位符”,表示这儿会有数据出现。一个“格式化字符串”中可以放置多个“占位符”,当程序进行打印输出时,这些“占位符”就会被真正的数据所替代。这些“占位符”都是以百分号“%”开头的,常用的占位符见表2.16。

表2.16 printf函数的占位符

通过在格式化字符串中使用占位符,可以很灵活地将一些实时的数据嵌入到输出字符串中进行打印,每一个占位符对应一种类型的数据。例如我们要使用printf函数来格式化打印一个学生的姓名、身高和体重,可以这样写:

在printf函数的格式化字符串中,出现了3个占位符:第一个占位符是“%s”,表示这儿会有一个字符串出现,在程序执行时,它会被后面的字符串常量"XiaoMing"所替代;第二个占位符是“%d”,表示这儿会有一个整数出现,在程序执行时,它会被后面的整型变量iHeight的值所替代;第三个占位符是“%f”,表示这儿会有一个浮点数出现,在程序执行时,它会被后面的浮点型变量fWeight的值所代替。所以在使用printf函数时,在格式化字符串中出现了多少个占位符,在后面就要跟上相应数量的参数。一个萝卜一个坑。

当所有的占位符都被后面的数据替代后,最终输出在控制台窗口上的文本字符串为:“Name:XiaoMing, Height:180cm, Weight:76.500000kg”。

细心的读者可能会发现,表示体重的浮点数的最后多出了5个0。这是正常的,因为默认对浮点数的输出格式就是要求保留6位有效小数。这么多的0跟在后面,是不是感觉不太美观?能不能改变一下,让它不出现0,或者少出现几个0呢?可以的,所以说printf函数功能强大,它除了可以使用占位符来给数据预留位置,还可以通过搭配“修饰符”来对这些数据进行输出格式上的精细控制,例如利用“控制符”来设置数据的输出宽度、对齐方式、数据精度等等。一些常用的“修饰符”见表2.17。

表2.17 printf函数的修饰符

这些修饰符是搭配占位符来使用的,不能单独使用。假如想让学生体重在输出的时候只保留两位有效小数,需要这样修改:

由原来的“%f”改为“%.2f”,这样就会让体重的输出结果只有两位小数,最终输出在控制台窗口上的文本字符串变为:“Name:XiaoMing, Height:180cm, Weight:76.50kg”。少了一大堆0,是不是感觉美观多了?

2.5.2 scanf函数

既然printf函数是用于打印输出的,那么有没有进行数据输入的函数呢?当然有,就是scanf函数。scanf函数与printf函数类似,第一个参数是一个“格式化字符串”,并且也可以根据需要来使用“占位符”和“修饰符”。scanf函数的功能是将用户在控制台窗口中的输入依据“占位符”的指示转换成相应类型的数据保存到变量中。再形象一些,用户使用键盘在控制台窗口里的输入虽然都是些字符,但通过“占位符”可以把这些字符理解为整型、实型、字符型或字符串等数据类型,把它们收集起来并存储在相应的变量中。

因为要将数据保存到变量中,所以在使用scanf函数时要注意,需要在后面的参数变量名前加上一个“&”符号,表示取变量的内存地址。至于为什么要加取地址符,现在不必纠结,等到后面学习使用指针的时候就明白了。

下面用例子展示一下scanf函数的使用方式。

在这个scanf函数中,格式化字符串里只有一个占位符“%d”,它表示将用户的输入按照整数的形式读取并保存到变量n中。变量n前面的“&”符号是必需的。

把这三行代码放在main函数中,编译生成可执行文件。然后执行程序时,会看到窗口中的光标不停地闪烁,它表示程序正在等待用户的输入。我们通过键盘在窗口输入一串数字字符“1234”,然后按下回车键,这时scanf函数就会把“1234”作为一个整数1234读取并保存到变量n中,最后会通过printf函数在窗口打印输出“you input integer is : 1234”。

如果我们把代码修改一下:

变量类型从int改为float,scanf函数中的占位符也就相应从“%d”改为“%f”。程序运行后,同样地,我们还是在窗口中输入一串数字字符“1234”,然后按下回车键。这次scanf函数就会把“1234”作为一个单精度浮点数读取并保存到变量flt中,最后通过printf函数在窗口打印输出“you input float is : 1234.000000”。

我们还可以使用scanf函数一次性读取多个不同数据类型的数据,例如:

在scanf函数的格式化字符串中连续有3个占位符,表示会分别把用户的输入按字符、整型和单精度浮点数的形式进行读取,并保存到相应的变量中。用户在输入时要注意,每个数据之间要留有空白字符(例如空格字符),不要连在一起,如:“A 100 3.14”,这样通过scanf函数最终会让变量ch的值为'A',变量n的值为100,变量flt的值为3.14。如果把所有输入字符都连在一起,如“A1003.14”,那么最终结果就会有所不同,变量ch的值依然为'A',但变量n的值变为1003,变量flt的值变为0.14。

下面再讲一下使用scanf函数时的一些注意点。

scanf函数在读取字符型数据时,会将用户输入的第一个字符(包含空白字符)读取进来,并保存到字符变量中。所谓空白字符包括空格、水平制表符以及换行符等这些不可见的字符。

scanf函数在读取非字符型数据时,会自动跳过用户输入中的前导空白字符,从第一个合法字符开始读取,直到遇到空白字符或非法字符时才停止读取,然后把这些字符转换成对应的数据保存到变量中。什么是合法字符呢?例如,如果读取的是一个十进制整数,合法字符就是指0~9这些数字字符;如果读取的是一个八进制数,合法字符就是指0~7这些数字字符;如果读取的是一个十六进制数,合法字符就是指0~9这些数字字符以及A~F、a~f这些字符;如果读取的是一个浮点数,那么合法字符除了包括0~9这些数字字符外,还包括一个表示小数点“.”的字符。

scanf函数的格式化字符串中尽量不要包含占位符之外的其他字符,因为用户必须严格按照格式化字符串的格式进行输入,否则很容易导致错误。

在此例中,格式化字符串内容为“Num:%d”,那么在程序执行后,如果想让变量n的值为1234,则用户在控制台窗口进行输入时,不可直接输入“1234”,必须严格按照格式进行输入,如“Num:1234”,否则就会造成读取错误,导致变量n得不到期望的数值。 Bvuoegtm2lPRWtSdmN8qlxewK3/VC3M4SEU/Xep4wc5MRCA4W1WccSB8OzFNhzNn

点击中间区域
呼出菜单
上一章
目录
下一章
×