在上一节课中我们学习了变量,有了变量我们就需要给变量输入值,就需要用到 scanf 函数 ,如果需要将变量的值输出在屏幕上就用到  printf函数 ,上代码: 

1   #include<stdio.h>
2   int main()
3   {   int a=0;
4       scanf("%d",&a);
5       printf("%d\n",a);
6       return 0;
7   }
    
    //scanf函数中,占位符后边的参数需要的是地址,&a,就是取出a的地址

 注:标准输入一般指键盘,标准输出一般指屏幕。

1.  基本用法

【敲重点】scanf 函数用于读取用户的键盘输入。

程序运行到这个语句时会停下来等待从用户从键盘输入。

用户输入数据、按下回车键,scanf()就会处理用户的输入,将其存入变量。

它的原型定义在头文件 stdio.h

scanf 与 printf 语法相似。

1    scanf("%d",&i);

它的第一个参数是一个 格式字符串 ,里面会放置占位符(与printf()的占位符基本一致),告诉编译器如何解读用户的输入,需要提取的是数据是什么类型。

因为C语言的数据都是有类型的,所以 scanf() 必须提前知道用户输入的数据类型,才能处理数据。

它的其余参数就是存放用户输入的变量,格式字符串里面有多少个占位符,就有多少个变量。

在上面的例子中,scanf()的第一个参数 %d ,表示用户输入的应该是一个整数。%d 就是一个占位符,% 是占位符的标志,d 表示整数。第二个参数 &i ,表示将用户从键盘输入的整数存入变量 i 。 

【注意】变量前面必须加 & (指针除外),因为 scanf 传递的不是值而是地址,即将变量 i 的地址指向用户输入的值。如果是指针变量就不需加 &。

上代码:

1   scanf ("%d%f%d",&a,&b,&c);

 %d%f%d ,表示用户输入的依次是整数、浮点数、整数。

【注意】scanf()处理数值占位符时,会自动过滤空白字符,包括空格、制表符、换行符等。

所以,用户输入的数据之间,有一个或多个空格不影响 scanf()解读数据;用户使用回车键,将输入分成几行,也不影响解读。

scanf()处理用户输入的原理是,用户的输入先放入缓存,等到按下回车键后,按照占位符对缓存进行解读。

解读用户输入时,会从上一次解读遗留的第一个字节开始,直到读完缓存,或者遇到第一个不符合条件的字符为止。

1   #include<stdio.h>
2   int main()
3   {
4       int a=0;
5       float b=0;
6       scanf("%d",&a);  //输入  “  -13.45e12# 0”
7       printf("%d\n",a);
8       scanf("%f",&b);
9       printf("%f\n",b)
10      return 0;
11   }

上面,scanf()读取用户输入时,%d  占位符会忽略起首的空格,从 - 处开始处理,读取到 -13 停下来,因为后面的 . 不属于整数的有效字符。%d 读取的就是  -13。

第二次调用 scanf()时,就会从上一次停止解读的地方继续往下读取。由于对应的占位符是 %f  ,所以从 "." 开始到 ".45e12",这是采用科学计数法的浮点数格式。后面的 # 不属于浮点数的有效字符,所以会停在这里。

由于 scanf()可以连续处理多个占位符,也可以这样写,上代码:

1   #include<stdio.h>
2   int main()
3   {
4      int a=0;
5      float b=0;
6      scanf("%d%f",&a,&b);
7      printf("%d %f",a,b);
8      return 0;
9   }

2.  scanf()的返回值 

scanf()的返回值是一个整数,表示成功读取的变量个数。

如果没有读取任何项或者匹配失败,则返回0。

如果在成功读取任何数据之前,发生了读取错误或者遇到读取文件结尾,则返回常量EOL(-1)

EOF - end of file  文件结束标志

1   #include<stdio.h>
2   int main()
3   { 
4       int a = 0;
5       int b = 0;
6       float f = 0.0f;
7       int r=scanf("%d %d %f",&a, &b, &f);
8       printf("a=%d b=%d f=%f",a, b, f);
9       printf("r = %d\n", r);
10      return 0;
11   }

如果输入2个数后,按 ctrl+z  ,提前结束输入:

 在VS环境中按3次 ctrl+z ,才结束了输入,我们可以看到 r=2 ,表示正确读取了2个数值。如果一个数字都不输入,直接按3次 ctrl+z ,输出的 r 是-1,也就是EOF 

3.  占位符

scanf()常用的占位符如下,与 printf()的占位符基本一致。

  • %c  :字符。
  • %d :整数。
  • %f  :float 类型浮点数。
  • %lf :double 类型浮点数。
  • %Lf :long double 类型浮点数。
  • %s :字符串。
  • %[ ] : 在方括号中指定一组匹配的字符(比如[0~9]),遇到不在集合之中的字符,匹配将会停止。 

上面所有占位符中,除了 %c 以外,都会自动忽略起首的空白字符。%c 不忽略空白字符,总是返回当前第一个字符,无论该字符是否为空格。

如果要强制跳过字符前的空白字符,可以写成 scanf(" %c, &ch"),即 %c 前加上一个空格,表示跳过0个或多个空白字符。

%s ,不简单等同于字符串。规则是:从当前第一个非空白字符开始读起,直到遇到下一个空白字符(空格、换行符、制表符等)为止。

因为 %s 不会包含空白字符,所以无法用来读取多个单词,除非多个 %s 一起使用。这也就意味着,scanf()不适合读取可能包含空格的字符串,比如歌名或书本名。另外,scanf()遇到 %s  占位符,会在字符串变量末尾存储一个空字符 \0 

scanf()将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,存储字符串时,很可能会超过数组的边界,导致预想不到的结果。所以,使用 %s 占位符时,应该指定读入字符串的最长长度,即写成 %[m]s ,其中的 [m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃。

1   #include<stdio.h>
2   int main()
3   {
4       char name[11];
5       scanf("%10s",name);
6       
7        return 0;
8   }

上面的例子中,name 是一个长为11的字符数组,scanf()的占位符%10s  表示最多读取用户输入的10个字符,后面的字符将被丢齐,这样就不会有 数组溢出 的风险了。

4.  赋值忽略符

有时,用户的输入可能不符合预定的格式。

1   #include<stdio.h>
2   int main()
3   { 
4       int year = 0;
5       int month = 0;
6       int day = 0;
7       scanf("%d-%d-%d",&year, &month, &day);
8       printf("%d %d %d\n",year, month, day);
9       return 0;
10      }

 例子中,如果用户输入2020-12-12,就会正确解读数据,但是如果输入2020/12/12,scanf()就会解析数据失败。

避免这种情况发生,scanf()提供了一个赋值忽略符 * ,只要把 * 加在任何占位符的% 后面,该占位符就不会返回值,解析后将被丢齐。

1   #include<stdio.h>
2   int main()
3   {
4       int year = 0;
5       int month = 0;
6       int day = 0;
7       scanf("%d%*c%d*c%d",&year, &month, &day);
8       return 0;
9   }

例子中,%*c  就是在占位符的百分号后面,加上了 赋值忽略符,表示这个占位符没有对应的变量,解读后不必返回。


完——

Show time! ———

一首歌送给你

————————————————       Jar of love      ——————————————————

Jar Of Love_曲婉婷_高音质在线试听_Jar Of Love歌词|歌曲下载_酷狗音乐酷狗音乐为您提供由曲婉婷演唱的高清音质无损Jar Of Lovemp3在线听,听Jar Of Love,只来酷狗音乐!icon-default.png?t=N7T8https://t1.kugou.com/song.html?id=dZmBL00CNV2

唉,别走,对,就是你,点赞收藏加关注哦——


再见——

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐