最最最详细的C语言教程笔记零起步(5)小白必备 同笔者一起学习

本文详细解析scanf函数的工作原理,包括其作为变参函数的使用方法、输入字符串匹配与转换、常见错误类型及避免策略,以及与printf的区别。特别关注字符和字符串输入,以及VS中关于scanf的使用注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

十一. scanf函数

printf函数将二进制表示的整数、浮点数、字符、字符串等按照转换规范转换成字符,并打印在控制台上。与之相反,scanf函数将键盘输入的字符串根据转换规范,转换成二进制表示的整数、浮点数、字符或字符串等。

#include <stdio.h>
 int main() 
{    
     char c;     
     short s;     
     int n;     
     long l;     
     float f;     
     double df;     
     
     scanf("%hhd %hd %d %ld %f %lf", &c, &s, &n, &l, &f, &df);       
     printf("%d %d %d %d %f %f\n", c, s, n, l, f, df);     

     return 0; 
}

在这里插入图片描述
注意 scanf_s
目前不讨论安全函数,可以右击解决方案的Project1,打开属性;进行操作。(5. 下面会讲到哦)
在这里插入图片描述

在这里插入图片描述

运行程序后,在键盘输入:“1 2 3 4 5.6 7.8”。scanf函数,将字符串"1 2 3 4 5.6 7.8",根据转换规范, 分别转换为各类二进制数据,并存储到变量中。
printf函数将这些变量,按照转换规范,再转换为字符串,输出到控制台。

1. scanf函数的使用公式

  1. scanf是一个变参函数。
  2. scanf的第一个参数是字符串。
  3. scanf的第一个参数内容为匹配字符以及转换规范。
  4. scanf的后续参数,是转换完成后,数据的存放位置。
  5. 转换规范的写法与数量,需要与后续的参数类型和数量对应。

1.1 scanf是一个变参函数

和printf一样,scanf也是一个变参函数。变参函数中参数的数量和类型不确定。

1.2 scanf的第一个参数是字符串

在这里插入图片描述

1.3 scanf的第一个参数为匹配字符串以及转换规范

在这里插入图片描述
请注意:输入时,需要按照第一个字符串的形式进行输入,否则无法得到正确结果。

例1: scanf第一个字符串为 “%hhd %hd %d %ld %f %lf” ,每个转换规范使用空格分割。那么输入时需要用空格进行分割,形如 1 2 3 4 5.6 7.8 。
例2: scanf第一个字符串为 “%hhd,%hd,%d,%ld,%f,%lf” ,每个转换规范使用 , 分割。那么输入时需要用逗号进行分割,形如 1,2,3,4,5.6,7.8 。
例3: scanf第一个字符串为 “%hhd+%hd-%dx%ld/%f~%lf” ,转换规范使用±x/~分割。那么需要像这样输入 1+2-3x4/5.6~7.8 。

总而言之,scanf会将输入的字符串与第一个参数进行匹配,从而找到需要转换的部分。 若字符串匹配失败,将无法得到正确的转换结果。

1.4 scanf的后续参数,是转换完成后,数据的存放位置

在这里插入图片描述
scanf将输入的字符串按照对应的转换规范进行转换,转换完成后的二进制,将依次存放到后续参数所输入的变量地址当中。暂时这里不讨论什么是变量的地址,请记住两个规则:

如果scanf将转换后的二进制存储到基本变量当中,请在变量名前加&。
如果scanf将字符串存储到字符数组中,字符数组名不用加&。

1.5 转换规范的写法与数量,需要与后续的参数类型和数量对应

scanf("%hhd %hd %d %ld %f %lf",&c,&s,&n,&l,&f,&df)

转换规范的写法与数量,需要与后续的参数类型和数量对应

参数数量参数类型
hhdchar
hdshort
dint
ldlong
ffloat
lfdouble

2. scanf函数具体做了什么

在这里插入图片描述

2.1 将输入字符串与第一个参数进行匹配

在这里插入图片描述

首先,scanf函数读取到输入的字符串。接着,scanf会将这个输入字符串与第一个参数的字符串进行匹配,找到输入字符串中的子串与转换规范的一一对应关系。

子串 “1” 对应转换规范 “%hhd”
子串 “2” 对应转换规范 “%hd”
子串 “3” 对应转换规范 “%d”
子串 “4” 对应转换规范 “%ld”
子串 “5.6” 对应转换规范 “%f”
子串 “7.8” 对应转换规范 “%lf”

2.2 根据转换规范将字符转换为二进制

子串与转换规范匹配好之后就开始转换环节。scanf将根据子串对应的转换规范,使用不同的转换方式,将子串转换为二进制。

不同转换规范代表的转换方式如下表:

长度指示符转换规范转换为某种类型的二进制
hhdchar
hdshort
dint
ldlong
长度指示符转换规范转换为某种类型的二进制
lldlong long
hhuunsigned char
huunsigned short
uunsigned int
luunsigned long
lluunsigned long long
ffloat
lfdouble
c字符对应的ASCII码
s字符串中字符对应的ASCII码

根据上表,对照例子中的转换方式如下。

子串 “1” 对应转换规范 “%hhd” ,将转换为char类型的二进制表示,1字节。
子串 “2” 对应转换规范 “%hd” ,将转换为short类型的二进制表示,2字节。
子串 “3” 对应转换规范 “%d” ,将转换为int类型的二进制表示,4字节。
子串 “4” 对应转换规范 “%ld” ,将转换为long类型的二进制表示,4字节。
子串 “5.6” 对应转换规范 “%f” ,将转换为float类型的二进制表示,4字节。
子串 “7.8” 对应转换规范 “%lf” ,将转换为double类型的二进制表示,8字节。
在这里插入图片描述

图片来自 你好编程

2.3 转换后的二进制放入变量

得到转换后的二进制后,将这些二进制根据顺序,依次放入变量当中。
在这里插入图片描述

图片来自 你好编程

由于使用了对应类型的变量来接收转换结果,所以长度和类型均可以保证一致。

3. 几类的错误示范

3.1 长度正确但类型错误

#include <stdio.h> 
 int main()
{     
     long long ll;
     scanf("%lf", &ll); 
     printf("%lld\n", ll);   
     printf("%f\n", ll);
      
     return 0; 
}

输入了字符串 “123.45” ,该字符串被转换规范 “%lf” 匹配。
接下来,字符串 “123.456” 将被转换为double类型的二进制表示,8个字节。
最后,这8个字节被送给了 long long 类型的变量 ll 。
现在变量ll是一个装有double类型二进制的整型了。

使用 %d 来打印ll肯定出现了错误的结果。
那使用 %f 来打印呢? %f 将取8个字节的二进制,并且按照double类型二进制规则进行转换。结果 就得到了正确的结果。

在这里插入图片描述

3.2 输入字符串数值大于转换类型取值

#include <stdio.h>
 int main() 
{     
     short s;     
     scanf("%hd", &s);     
     printf("%d\n", s);     

     return 0; 
}

输入了字符串 “2147483467” ,该字符串被转换规范 “%hd” 匹配。
接下来,字符串 “2147483467” 将被转换为short类型的二进制表示,2个字节。
而short类型的取值范围为 -32767~32768 , 2147483467 无法用short装下。
所以,无法得出正确的结果。

在这里插入图片描述

3.3 变量放不下转换结果

#include <stdio.h>
 int main() 
{     
     short s;     
     scanf("%d", &s);     
     printf("%d\n", s);     

     return 0; 
}

输入了字符串 “2147483467” ,该字符串被转换规范 “%d” 匹配。
接下来,字符串 “2147483467” 将被转换为int类型的二进制表示,4个字节。
最后,转换后的4个字节的数据被short类型的变量s接收,丢失了2个字节。
所以,无法得出正确的结果。

在这里插入图片描述

3.4 如何避免错误

#include <stdio.h>
int main()
{
    int n;
    scanf("%d", &n);
    printf("%d\n",n);

    return 0;
}

我们输入了字符串 “2147483467” ,该字符串被转换规范 “%d” 匹配。
接下来,字符串 “2147483467” 将被转换为int类型的二进制表示,4个字节。
最后,转换后的4个字节的数据被int类型的变量n接收。
正确结果。
使用scanf的时候请注意,输入字符串的数值转换规范和接收转换结果的变量类型必须匹配才能得到 正确结果。

在这里插入图片描述

4.字符和字符串

4.1 输入字符

#include <stdio.h>
int main()
{   
    char c;
    scanf("%c", &c);
    printf("%d %c\n", c, c);
    return 0;
}

在这里插入图片描述
输入了字符串 “A” ,该字符串被转换规范 “%c” 匹配。
接下来,字符串 “A” 将被转换为char类型的二进制表示(其十进制为65),1个字节。
最后,转换后的1个字节的数据被char类型的变量c接收。
当用 %d 打印c时,输出了数值 65 。而用 %c 打印时,输出了字符 A 。

#include <stdio.h>
 int main() 
 {   
     char c;     
     scanf("%hhd", &c);     
     printf("%d %c\n", c, c);     
     
     return 0; 
 }

在这里插入图片描述
如果要给char类型输入数值,请使用转换规范 %hhd 。若还使用转换规范 &c 。会将第一个字符的ASCII码装入变量。

4.2 输入字符串

#include <stdio.h>
 int main() 
 {
     char str[10];     
     scanf("%s", str);     
     printf("%s", str);     
     
     return 0; 
 }

在这里插入图片描述

c语言中没有字符串变量,字符串被存储在字符数组当中。 由于这里是将输入的字符串存储到字符数组中,后面的参数str不加&。 目前还没有讨论过数组,暂时不继续展开这一部分内容。

5. VS无法使用scanf函数

如果你使用的是较新版本的Visual Studio,scanf这类函数会被认为是不安全的,编译器会抛出C4996错 误,并建议你使用别的安全函数替代。
但是,目前我们并不想引入并讨论这一类安全函数。请将 _CRT_SECURE_NO_WARNINGS 加入预定义字符串, 屏蔽不安全函数错误。

如图所示:
在这里插入图片描述
在这里插入图片描述

6. scanf与printf的不同

  1. printf的后续参数不要加&,而scanf由于需要一个地址,所以对于基本变量需要加&,数组则不需要。
  2. printf的参数由于比int小的变量会升级为int,float会升级为double。所以,转换规范 d 可以用于char,short,int。转换规范f可以用于float和double。但是scanf是直接把转换结果送到接收变量中,必须严格使用转换规范。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

没有余地 EliasJie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值