前言
scanf与printf是两个库函数,它俩是一对,scanf用于输入;printf用于输出。那么什么是库函数呢?C语⾔并不提供库函数,C语⾔标准中规定了C语⾔的各种语法规则;C语⾔的国际标准ANSIC规定了⼀ 些常⽤的函数的标准,被称为标准库,不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列函数的实现,这些函数就被称为库函数。需要使用这些库函数就得要包含它们相关的头文件,这里给大家推荐两个链接用于查看库函数跟库函数所需的相关头文件
(库函数相关头⽂件:https://zh.cppreference.com/w/c/header)
(C/C++官⽅的链接:https://zh.cppreference.com/https://zh.cppreference.com/w/c/header )
下面我们进入主题来详细讲讲scanf与printf这两个库函数。
一.printf
1.使用方法
printf实则是print和f(format),就是格式化打印的意思;printf函数的用途是将参数文本输出到屏幕上,也能指定格式输出文本。我们查看这个库函数可以看到关于printf函数的介绍:
int printf( const char *format [, argument]... );这段话就描述了该怎么使用printf这个函数,翻译一下大概就是:printf接收一个格式化字符串(const char *format)作为函数的主要参数,([,argument] ...)这个的意思是后面可以跟任意数量的参数;这里的参数数量取决于我们使用的占位符数量,下面会给大家介绍到这个占位符,并且所跟的参数需跟占位符相对应不然会打印出不是我我们需要的值甚至会打印出错!C语言语法规定字符串需要使用(" ")英文的双引号括起来,而参数与参数之间需要用英文的(,)逗号隔开。
我们还可以看到在printf的前面还有一个int,那么这个int是什么意思呢?是这个函数是int型的?其实这个是表示printf这个函数的返回值的是整数,那么它的返回值又是什么呢?
这里就描述了这个函数是怎么返回它的值的,翻译过来就是:每个这些函数都会返回所打印字符的数量,如果出现错误则返回一个负值。
最后我们需要使用printf这个函数还需要包含它的头文件<stdio.h>,下面我们通过一段简单的代码来看看:
可以看到代码执行后屏幕上打印出来了: hello!!!
我们再来看一段代码:
可以发现同样也打印了:hello!!!,不同的是比上面多空出来了一行;这是为什么呢?这次的代码后面多了一个“\n”,是它引起的吗?确实是的,“\n”为一个转义字符是换行用的,printf打印完光标会停留在最后一个字符的后面,我们加上“\n”可以让光标换到下一行,“\n”可以插在文本的任意位置,换行后还有文本没有打印完会继续打印;可以在需要换行的位置插入“\n”,达到换行打印的目的。
2.占位符
什么是占位符呢?从字面意思可以看出来就是占位置用的,不知道大家有没有看到过在上课的教室或者食堂里有时候会有些没有人坐的位置,这些位置上会被放了一些东西,我们便知道这大概率是有人占掉了这个位置。那么C语言里的占位符又是什么样的呢?让我们一块来看看:
占位符都是以%(百分号)开头的,我们可以在字符串中插入占位符,也可以只将占位符作为主要参数。那么都有哪些占位符呢?
常用的: | |||
---|---|---|---|
%c | 字符 | %s | 字符串 |
%d | 十进制的整数(int) | %f | float型浮点数 |
%lf | double型浮点数 | %hd | 十进制short int型 |
%hu | unsigned short int型 | %ld | 十进制long int型 |
%lu | unsigned long int型 | %Lf | long double型浮点数 |
%p | 指针(用来打印地址) | %u | 无符号整数(unsigned int) |
%x | 十六进制整数 | %zd | size_t类型(sizeof的返回值) |
不太常用的: | |||
%a | ⼗六进制浮点数,字⺟输出为⼩写 | %A | ⼗六进制浮点数,字⺟输出为⼤写 |
%e | 使⽤科学计数法的浮点数,指数部分的 e 为⼩写 | %E | 使⽤科学计数法的浮点数,指数部分的 E 为⼤写 |
%g | 6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 e 为⼩写 | %G | 6个有效数字的浮点数。整数部分⼀旦超过6位,就会⾃动转为科学计数法,指数部分的 E 为⼩写 |
%ho | ⼋进制short int类型 | %hx | ⼗六进制short int类型 |
%lo | ⼋进制long int类型 | %lx | ⼗六进制long int类型 |
%lld | ⼗进制long long int类型 | %llo | ⼋进制long long int类型 |
%llx | ⼗六进制long long int类型 | %llu | unsignedlong long int类型 |
%Le | 科学计数法表⽰的longdouble类型浮点数 | %n | 已输出的字符串数量。该占位符本⾝不输出,只将值存储在指定变量之中 |
%o | ⼋进制整数 | %i | 整数,基本等同于 (%d) |
%% | 输出⼀个百分号 |
占位符表示该位置已经被占用了,会用其他值来替换它;下面给大家给大家介绍几个占位符的使用:例如%d,它表示带入的值必须是一个整数,那带入不是整数的值又会怎么样?我们通过代码来看看
可以看到占位符%d的位置确实被替换为了其他值,并且带入的值给的是整数可以被准确打印出来;但是给的值不是整数,就不能准确打印出来了而且我们可以看到编译器会报出来警告,在换成打印浮点数的%lf时又可以被准确的打印出来了;所以我们在使用占位符时若发现打印的不是我们想要的值时,可以检查占位符是否使用错了。
仔细观察最后一个代码可以发现其实使用的是%.1lf,那么这又是什么意思呢?在%后的这个(.1)是只打印一位小数的意思;如果改成(.2)就是打印两位小数。接下来我们就来讲一下关于格式出的更多细节!
3.格式输出的细节
-
限定宽度
在占位符的%号后面加上数字,便可以指定占位符的宽度;例如%2d,表示最少输出两位;如果不满两位则会在前面添上空格。如写成%02d,不满两位则会在前面补0。输出的值默认是右对齐的,如果需要左对齐则需要在%后面在添上“ - ”(负号)。
对于小数则是限定所有数字的最小宽度,例如%10f,表示输出的浮点数最少为10位;假如打印3.14f(f表示3.14为float型的浮点数,不加f编译器会默认是double型的浮点数)时,由于浮点数的默认显示精度是6位,所以3.14前面还会输出两个空格。
-
显示数据的符号
在输出数据需要一直显示数据的符号时,可以在%号后面加上“ + ”正号;因为负数本身便会带上负号在一个负数前面加上一个“+”(正号)也不会影响到负数;而正数的符号默认是被隐藏的,所以加上“+”,正数也会显示符号了。
-
限定小数位数
在前面我们已经用到过限定小数位数,就是在%号后面加上“ .”(点)和需要位数的数字。这里在说一点,限定小数位数可以与限定宽度连用。例如我们还是打印3.14,这次我们指定小数点位数为3位;限定宽度还是10,结果会是什么样子的呢?我们通过代码来看看:
可以发现我们指定的打印三位小数和宽度为10;结果也只打印了三位小数,但是多打印了三个空格,所以总共也是打印了10位。
并且我们在限定宽度和小数点位数时的数字可以用“ * ”,先代替再通过参数来传递。
-
字符串部分输出
使用%s占位符时默认是将字符串全部输出;如需要只输出字符串的前几位可以在%号后加上.[n];n表示想要输出的位数,例如只想要输出字符串的前三位就可以这样写:%.3s。
二.scanf
1.使用方法
scanf函数基本语法与printf函数类似,可以从键盘读取输入的信息。它的第一个参数是格式化字符串,里面会放入占位符与printf函数的占位符基本一致;使用sancf后程序运行到这个语句时会停下来等待用户输入,用户的输入格式需与第一个参数的格式一致才能处理数据。scanf函数用于将输入的信息赋值给变量,将变量作为参数时,需要在变量前加上“&”(取地址符),指针变量除外。
下面我们通过一段代码来了解一下scanf函数的基本使用:
可以看到变量a里开始放的是10,我们通过scanf函数可以把2变量a改成了20。
这里使用的编译器是vs2022,其实在vs中直接使用scanf函数编译器会报错,我们来看看:
为什么会出现这个错误呢?是因为vs这个编译器会认为sacnf这个函数不安全,建议改成scanf_s;这样改确实可以使用了但是不建议!因为这样的话你把你的代码放到其他编译器下就可能编译不通过了,那该怎么办呢?我们还能使用(_CRT_SECURE_NO_WARNINGS)来解决这个问题,该怎么用呢?通过在代码行的第一行加上(#define _CRT_SECURE_NO_WARNINGS)就可以解决这个问题了。(本人会在后面单独写一篇博客来给大家讲讲怎样一劳永逸的解决这个问题的方法,有需求的话可以关注一下后续)
2.读取与scanf函数的返回值
在我们输入数据后scanf又是怎样来分辨数据的呢?
- scanf()在处理数值占位符时会自动过滤掉空⽩字符,(即空格、换⾏符、制表符等)一直读取到非该类型的值时才会停下来,并且把读取到的值作为第一个占位符的内容,再开始读取后面的数据,直到给占位符都读取到了内容。
- 在处理%c这个占位符时不会跳过空白字符,因为空白字符实则也是一个字符;
- 在处理%s时会从当前第⼀个⾮空⽩ 字符开始读起,直到遇到空⽩字符为⽌,并且scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。在储存字符串时, 不注意的话可能会超过数组的边界,导致预想不到的结果。我们可以在使用%s时在%号后面加上整数数字来限定读取字符串的最大长度。
那么scanf( )的返回值又是什么呢?它的返回值是⼀个整数,这个整数是成功读取的变量个数。 如果没有读取任何项,或者匹配失败,则返回 0 。 如果在成功读取任何数据之前,发⽣了读取错误或者遇到读取到⽂件结尾,则返回常量EOF(-1)
3.赋值忽略符
什么又是赋值忽略符呢?是干啥用的呢?scanf( )提供的赋值忽略符是“ * ”,是为了避免用户输入其他格式导致scanf( )解析数据失败用的。只需要在%后加上*该占位符就不会返回值,解析后将被丢弃。我们通过一段代码来看看。
按照格式输入,可以正常打印:
没有按照格式输入,则会读取失败:
使用赋值忽略符之后,多种输入均可以:
结语
以上就是全部内容啦,十分感谢您能看完这篇博客;如果对您有帮助,我将感到非常荣幸,如有讲的不对的地方还请麻烦指出,以免误导了别人。再次感谢您的阅读。