第八节 输入/输出

Blaze,你终于也开始学C了哈哈哈哈XD

我们已经知道,C语言会使用scanf()printf()来进行输入/输出。关于这两个函数,我们在这里再做深入的了解。

printf()函数

printf()函数会把所有类型的数据转换成字符串,并打印在屏幕上。它的标准格式是:

printf("格式字符串",待打印值1,待打印值2……);

其中,格式字符串需要包括“实际打印的字符”与“转换说明”。而且转换说明的数量、类型都要与后面的打印值相匹配。打印值可以是常量、变量或者合法的表达式。如果转换说明与打印值不匹配,编译器不会报错。printf()函数本质上使用的是

特别需要注意的是:由于函数内的转换说明都以“%”作为开头,所以我们在打印“%”号时,需要在前面再加一个%。

例如,要打印“存在【变量值】%的风险”这个语句。就要写成:

printf("存在%d%%的风险。",risk);

修饰转换说明

如果在%和转换字符中插入修饰符,就可以修饰基本的转换说明。如果要插入多个修饰符,就应当遵循一定的顺序。我们来详细讲解这些说明。

标记

常见的转换说明标记有五种:**减号、加号、空格、井号和0。**它们的含义如下:

  1. 减号:待打印项左对齐
  2. 加号:在有符号值的前面显示符号。正值显示正号,负值显示负号;
  3. 空格:同加号类似,不过正值不显示符号而显示空格;
  4. 井号:把结果转换成另一种显示形式。例如:在打印十六进制数时,使用井号可以在数字前面附上0x前缀。在浮点格式转换说明前加上井号,就能使函数固定打印一位小数;
  5. 0:代替空格填充字段宽度。在前面加上几个0,打印时就会在前面多出几个0。
数字与.数字

在%号后插入数字,代表最小字段宽度。即在打印时,系统会使用规定的字段宽度打印。如果字段宽度不足以容纳打印的值,系统会自动扩宽字段宽度。

在%号后插入.数字,代表精度。具体如下:

  1. 对于%e/%f转换,表示小数位数
  2. 对于%s转换,表示打印字符的最大数量
  3. 对于%d转换,表示最小位数

我们通过下面的程序来演示修饰转换说明的效果:

//modify.c 演示修饰转换说明
#include <stdio.h>
#define NUM 123
int main(void)
{
    float fl = 1.23456;

    printf("|%d|\n", NUM);
    printf("|%2d|\n", NUM);//数字
    printf("|%10d|\n", NUM);//长数字
    printf("|%10f|\n", fl);
    printf("|%.2f|\n", fl);//.数字
    printf("|%10.2f|\n", fl);//数字和.数字共用
    printf("|%+10d|\n", NUM);//加号
    printf("|%-10d|\n", NUM);//减号
    printf("|%#x|\n", NUM);//井号
    printf("|%05d|", NUM);//0

    return 0;
}

试运行,输出结果如下:

|123|
|123|
| 123|
| 1.234560|
|1.23|
| 1.23|
| +123|
|123 |
|0x7b|
|00123|

我们来详细解释:

  1. 第一行未作任何变化;
  2. 第二行限制了最小字段宽度,但由于字段宽度不能容纳下所需要打印的值,所以编译器自动扩宽了字段宽度;
  3. 第三行限制了最小字段宽度,所以程序打印这个值的总宽度是10;
  4. 第四行同上;
  5. 第五行限制了精度,所以打印时精确到小数点后2位,这里遵循四舍五入;
  6. 第六行是数字和.数字共用。在同时使用的时候,要遵循这样的规则;
  7. 第七行使用了加号,所以在有符号数NUM的前面加上了正号;
  8. 第八行使用了减号,所以编译器将要打印的值左对齐,从左打印;
  9. 第九行使用了减号,所以在十六进制数7b的前面加上了0x前缀。
  10. 第十行使用了0,所以在打印时前面加上了相应个数的0。

(扩展:当使用%e转换说明时,.数字代表指数)

在字符串中,也有着相似的修饰方法:

//string_modify.c 演示字符串修饰转换说明
#include <stdio.h>
#define NAME "Briue Rua"
int main(void)
{
    printf("|%2s|\n", NAME);
    printf("|%12s|\n", NAME);
    printf("|%12.3s|\n", NAME);
    printf("|%-12.3s|\n", NAME);
    
    return 0;
}

运行结果如下:

|Briue Rua|
| Briue Rua|
| Bri|
|Bri |

可以发现,数字仍然代表最小字段宽度,.数字则是代表打印的字符个数。

转换说明不匹配

通常,打印一个值时,使用多种类型的转换说明都是可行的。例如,打印10这个整数,可以使用%d,%x等转换说明。但是,转换说明如果与值不匹配,会发生一些问题。这些问题的原理较为复杂。可以参考这里

printf()的返回值

绝大多数函数都有返回值。printf()也不例外。它的返回值是打印字符的个数(包括非打印字符)。如果出现输出错误,则返回一个负值。

scanf()函数

scanf()是较为常用的输入函数。我们只能从键盘上输入字符。例如,当我们输入整数“123”时。我们实际输入的是字符1、2、3。scanf()的目的就是要把字符串转换成对应类型的数据,这和printf()函数正好相反。它的标准格式是:

scanf("%数据类型的转换说明",&变量名)//当变量是字符数组时,不要使用&。

在 C 语言中,数组名本身就代表数组首元素的地址,也就是数组在内存中的起始地址。因此,当使用 scanf 函数读取字符串并存储到字符数组中时,不需要使用 & 来取地址。

我们已经知道,scanf()函数在遇到空格、换行符或制表符时会停止读取输入。但是%c除外。我们将在后面详细讨论这个问题。

scanf()中的转换说明,用来指示scanf()函数把输入的字符解释成什么数据。它们的用法大致与printf()函数相同。但是把数据解释成double类型时要使用**l**修饰符。

scanf()输入的原理

我们现在详细研究scanf()函数。假设有以下语句:

int num;
scanf("%d",&num);

这两条语句要求scanf()函数根据%d转换说明读取一个整数。接下来,scanf()函数每次读入一个整数(或者正负号),并把它放入缓冲区,这个过程直到遇见非数字字符为止。比如,假如用户的输入是123q456,那么scanf()就会逐一读取1、2、3,直到遇到q,它就会认为已经读到了整数的末尾,于是停止读入。

然后,scanf()会把非数字字符放回输入。程序在下一次读取输入时,首先遇到的是上一次留下的非数字字符。

最后,scanf()将计算缓冲区内已读取到的数字的值,并将它存储进指定的变量中。

放回输入后,如果下一个scanf()仍然使用%d转换说明,那么它遇到的第一个字符不是4,而是q。所以,它会停下并将数据放回输入中,假如后面的scanf()都使用%d转换说明,就会一直无法读取输入。

使用其他转换说明的方式和上述类似。不过读取的范围会有所不同*(例如%x会读取大小写的A~F)*。在使用%s转换类型时,scanf()函数会读取除空白字符外的所有字符(也就是一个中间无空格的单词)。

假如我们使用数字修饰符限定转换说明,那么scanf()会在字段终止或遇到不满足条件的字符时(满足其一)停止。

scanf()的其他特性

scanf()允许把普通字符放在格式字符串中。除了空格字符以外,输入的字符串必须与格式字符串严格匹配。例如:

scanf("%d,%f",&num,&fl);

scanf()函数会将其解释成:用户会先输入一个整数,再输入一个逗号,最后输入一个浮点数。用户必须以这样的方式输入两个数字,否则程序便不会正常运行。

如果在格式字符串中把空格放到%c的前面,scanf()函数就会从第一个非空白字符处读取(而不是从第一个字符处开始)。

scanf()的返回值

scanf()返回成功读取的项数。如果没有读取到任何项,而且读取到的字符串和转换说明不匹配,那么就会返回0。我们将在之后详细讨论scanf()函数返回值的运用(处理不匹配的输入)。

星号修饰符

在printf()函数中,我们在转换说明中加入*修饰符,能够代替数字和.数字修饰符。但是需要在后面指示*代替的数字。例如:

printf("%*.*f",width,precision,fl);

在scanf()函数中,*修饰符会使得scanf()函数跳过相应的输入项。例如:

scanf("%*d %d",&num);

它的意思是:跳过第一个用户注入的整数,把第二个整数赋给num。

关于星号修饰符的更多内容见此

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值