C语言的printf函数与scanf函数详解

目录

3.1 printf函数

3.1.1 占位符

3.1.2 转义字符

3.2 scanf函数

3.2.1 scanf函数的工作方法(重要)

3.2.2 格式串中的普通字符

3.2.3 易混淆的printf函数与scanf函数


3.1 printf函数

作用: 显示格式串的内容 (常量 or 变量 or 表达式)
注意事项: 调用 printf 函数时需要提供格式串
printf(格式串, 表达式 1, 表达式 2, ...);

int main()
{
    int height = 8;
    printf("Height = %d",height) //​​​​​​printf("Height = 格式串1",表达式1);
    return 0;
}

  格式串包含普通字符占位符(以字符%开头)

3.1.1 占位符

基本概念:用于指示printf函数把数值从内部形式(二进制)转换成打印形式(字符)的方法

例如,占位符%d 指示 printf 函数把 int 型值从二进制形式转换成十进制数字组成的字符串

#include <stdio.h>
int main()
{
    int i, j; 
    float x, y; 

    i = 10; 
    j = 20; 
    x = 43.2892f; 
    y = 5527.0f; 

    printf("i = %d, j = %d, x = %f, y = %f\n", i, j, x, y);

    return 0;
}

注意事项:

1、C 语言编译器不会检测占位符的数量是否与输出项的数量相匹配,也不会检测占位符指示

换方式与输出项的类型是否匹配,这些都需要自行检查

printf("%d %d\n", i); /*** WRONG ***/

printf("%d\n", i, j); /*** WRONG ***/

printf("%f %d\n", i, x); /*** WRONG ***/

2、占位符也可以显示格式化信息,即%m.pX 格式%-m.pX 格式m p 都是整型常量,X 是字母,m p 都是可选的。如果省略 pm p 之间的小数点也要去掉。

%10.2f   %10f                   %.2f 
m = 10   10                     m省略了但是.不省略
p = 2    p连带小数点一起被省略   2
x = f    f                      f                      

3、最小栏宽 m 指明了要显示的z少字符数量:

  1. 如果要显示的数值所需的字符数少于 m,那么值在字段内是右对齐的(在值前面放置额外的空格)(%4d 将以“空格123” 的形式显示数123)
  2. 如果要显的数值所需的字符数多于 m,那么栏宽会自动扩展为所需的尺寸(%4d 将以12345的形式显示数 12345,而不会丢失数字)
  3. m 前放上一个负号会导致左对齐(%-4d 将以“123空格”的形式显示 123)

4、精度 p 依赖于转换指示符 X 的选择,X表明在显示数值前需要对其进行哪种转换,对数值来说

常用的X有以下几个:

  • %d:表示十进制形式的整数。p 指明了待显示数字的少个数,默认为1(不足左侧补零)
  • %e:表示指数形式的浮点数。p 指明了小数点后应该出现的数字个数 (默认值为 6),如果 p 为 0,则不显示小数点。
  • %f:表示“定点十进制”形式的浮点数,没有指数。p 的含义与 e 中的一样。
  • %g:表示指数形式或者“定点十进制”形式的浮点数,形式的选择根据数的大小决定。p 指明可以显示的有效数字(不是小数点后的数字)的数量。与 f 不同,g 的转换将不显示尾随的零。此外,如果要显示的数值没有小数点后的数字,g 就不会显示小数点。

5、编写程序时无法预知数的大小或者数值变化范围很大的情况下,g 对于数的显示是特别有用的。在用于显示大小适中的数时,g 采用“定点十进制” 形式。但是在显示非常大或非常小的数时,g 会转换成指数形式以便减少所需的字符数

3.1.2 转义字符

基本概念: 包含特殊字符 (\、?等) 的字符串称之为转义字符
常见的转义字符有:
  • 警报(响铃)符:\a
  • 回退符:\b
  • 换行符:\n
  • 水平制表符:\t
        当这些转义字符出现在 printf 函数的格式串中时,它们表示在显示数值时执行的操作。
在大 多数环境中 ,输出\a 会产生一声鸣响,输出\b 会使光标从当前位置回退一个位置,输出
\n 会使光 标跳 到下一行的起始位置,输出\t 会把光标移动到下一个制表符的位置。
注意事项:
1、字符串可以包含任意数量的转义序列
printf("Item\tUnit\tPurchase\n\tPrice\tDate\n");

输出结果:
Item  Unit  Purchase 
      Price  Date

2、\" 也是转义字符,它表示字符",因为字符 " 标记字符串的开始和结束,所以 \" 不能出现在没

有使用上述转义字符的字符串内

printf("\"Hello!\"");

输出结果:"Hello!"

3、不能在字符串中只放置单独一个字符 \ ,编译器将认为它是一个转义序列的开始,为了单独显

示字符 \ ,需要在字符串中放置两个字符 \ 

printf("\\");

3.2 scanf函数

基本概念:scanf 函数与printf函数一样也是由格式串控制的

scanf("%d%d%f%f", &i, &j, &x, &y);
假设用户录入了下列输入行:
1 -20 .3 -4.0e3
        scanf 函数将读入上述行的信息,并且把这些符号转换成它们表示的数,然后分别把 1、-20
0.3 和-4000.0 赋值给变量 ijx y
注意事项:
1、scanf函数在读取输入的内容时会自动跳过空格 
2、scanf 函数调用中像"%d%d%f%f"这样“紧密压缩”的格式串是很普遍的,而printf函数罕见
3、一般情况下scanf 函数的格式串只包含转换说明
4、使用scanf函数时必须检查占位符的数量是否与输入变量的数量相匹配,并且检查每个占位符
指明的类型是否与变量类型相匹配,编译器无法检查出可能的匹配不当
5、&被放在 scanf 函数调用中的每个变量的前面,&常常是需要的(加上就行,少数情况不用)
!!!如果 scanf 函数调用中忘记在变量前面放置符号&, 将产生不可预知甚至可能是毁灭
性的结果 。程序崩溃是常见的结果。最轻微的后果则是从输入读进来的值无法存储到变量
中,变量将保留原有的值 (如果没有给变量赋初始值,那么这个原有值可能是没有意义的)
忽略符号&是极为常见的错误,一定要小心!一些编译器可以检查 出这种错误,并产生一条
类似“format argument is not a pointer”的警告消息。 如果出现该警告消息, 检查一下是
否遗漏了符号&。
6、调用 scanf 函数是读数据的一种有效但不理想的方法。许多专业的 C 程序员会避免使用 scanf
函数,而是采用字符格式读取所有数据,然后再把它们转换成数值形式(我也很好奇是什么方式)

3.2.1 scanf函数的工作方法(重要)

基本概念:像 printf 函数一样,scanf 函数是由格式串控制的。调用时,scanf 函数从左边开始处

理字符串中的信息。对于格式串中的每一个占位符,scanf 函数从输入的数据中定位适当类型的
项,并在必要时跳过空格。然后,scanf 函数读入数据项,并且在遇到不可能属于此项的字符时停
止。如果读入数据项成功,那么 scanf 函数会继续处理格式串的剩余部分;如果某一项不能成功
读入,那么 scanf 函数将不再查看格式串的剩余部分 (或者余下的输入数据) ,并立即返回。
注意事项:
1、在寻找输入数值的起始位置时,scanf 函数会忽略空白字符(包括空格 符、 水平和 垂直制表
符、换页符和换行符)因此,我们可以把数字放在同一行或者分为几行来输入
scanf("%d%d%f%f", &i, &j, &x, &y);

用户的三行输入:
1
-20  .3
     -4.0e3

scanf 函数会把它们看作一个连续的字符流:
· · 1 ¤ - 2 0 · · · . 3 ¤ · · · - 4 . 0 e 3 ¤ (提交时,会再次输入一个换行符,你总的enter吧)  
s s r s r r r s s s r r s s s s r r r r r r 
·表示空格符,¤表示换行符,s表示此项被跳过,r 表示此项被读取为输入项的一部分

2、scanf 函数“忽略”了最后的换行符,实际上没有读取它。这个换行符将是下一次 scanf 函数调

用读取的第一个字符,该换行符就会被放在输入缓冲区中(十分重要!!)

3、scanf 函数识别整数的方式: 先寻找正负号,然后读取数字,直到读到一个非数字时才停止。
4、scanf 函数识别浮点数的方式: 先寻找一个正负号 (视情况而定) ,随后是一串数字 (可能含
有小数点) ,再往后是一个指数 (视情况而定)(指数由字母 e 或 E、可选的符号,以及一个或多
个数字构成)
5、当 scanf 函数遇到一个不可能属于当前项的字符时,它会把此字符“放回原处”,以便在扫描下
一个输入项或者下一次调用 scanf 函数时再次读入
scanf("%d%d%f%f", &i, &j, &x, &y);

用户输入:1-20.3-4.0e3¤

用户想要的:1、-2、0.3、-4000

实际的结果:1、-20、0.3(读取.3后自动补零)、
下面是 scanf 函数处理这组(错误)输入的方法:(十分重要!!!)
  • 占位符%d:第一个非空的输入字符是 1;因为整数可以以 1 开始,所以 scanf 函数接着读取下一个字符,即-scanf 函数识别出字符-不能出现在整数内,因此把 1 存入变i 中,而把字符-放回原处。
  • 占位符%d:随后,scanf 函数读取字符-20 .(句点)。因为整数不能包含小数点,所以 scanf 函数把–20 存入变量 j 中,而把字符.放回原处。
  • 占位符%f:接下来 scanf 函数读取字符.3 -。因为浮点数不能在数字后边有负号,所以 scanf 函数把 0.3 存入变量 x 中,而把字符-放回原处。
  • 占位符%f:最后,scanf 函数读取字符-4.0e3 ¤(换行符)。因为浮点数不能包含换行符,所以 scanf 函数把–4.0×103存入变量 y 中,而把换行符放回原处。

3.2.2 格式串中的普通字符

处理格式串中的普通字符时,scanf 函数采取的动作依赖于这个字符是否为空白字符:

  • 空白字符:当在格式串中遇到一个或多个连续的空白字符时,scanf 函数从输入中重复读空白字符,直到遇到一个非空白字符为止(同时会把该非空白字符“放回原处”)
  • 非空白字符:当在格式串中遇到非空白字符时,scanf 函数将把它与下一个输入字符进行比较。如果两个字符相匹配,那么 scanf 函数会放弃输入字符,并继续处理格式串。如果两个字符不匹配,那么 scanf 函数会把不匹配的字符放回输入中,然后异常退出,而不进一步处理格式串或者从输入中读取字符

scanf("%d/%d");

用户输入:[空格]5/[空格]96

        scanf 函数会跳过第一个空格,把%d 与 5 匹配,把//匹配,在寻找下一个整数时跳过一个空格,并把%d 与 96 匹配

scanf("%d/%d");

用户输入:[空格]5[空格]/[空格]96

        scanf 函数会跳过第一个空格,把%d 5 匹配,然后试图把格式串中的/与输入中的空格匹

配。但是二者不匹配,因此 scanf 函数把空格放回原处,把字符·/·96 留给下一次 scanf 函数调用

来读取,故为了使得scanf函数不会进行第二次调用,应使用格式串"%d[空格]/%d",此时%d之间

的空格就可以很好的把整数5和/之间没有用的空格抵消掉,这也是建议scanf函数的每一个占位符

之间都有一个空格的原因

3.2.3 易混淆的printf函数与scanf函数

        虽然 scanf 函数调用和 printf 函数调用看起来很相似,但这两个函数之间有很大的差异, 忽
略这些差异就是拿程序的正确性来冒险,以下是常见的错误行为
1、执行 printf 函数调用时在变量前面放置&
printf("%d %d\n", &i, &j); /*** WRONG ***/

2、scanf格式串类似于printf格式串

scanf("%d, %d", &i, &j);
         scanf 函数首先寻找输入中的整数,把这个整数存入变量 i 中;然后,scanf 函数将试图把逗
号与下一个输入字符相匹配。如果下一个输入的字符是空格而不是逗号,那么 scanf 函数将终止
操作,而不再读取变量 j 的值。
3、在 scanf 格式串末尾放置换行符
scanf("%d\n");
        对 scanf 函数来说,格式串中的换行符等价于空格,两者都会导致 scanf 函数提前进入
下一个非空白字符。 像这样的格式串可能会导致交互式程序一直“挂起”,直到用户输入一个
非空 白字符为止。

~over~

  • 20
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值