printf函数和scanf函数介绍!!!
- printf函数:这个函数,我们在之前的文章里见过了。那在本章中,我们进行详细的讲解。printf的全名是:print—formate—打印格式。在屏幕上进行信息的打印(输出信息)。
- printf的打印: 我们在之前有见过它的打印格式。比如,
printf("Hello,World");
和printf("%d ", 5);
。前面一种的方式,是进行字符串的打印。当打印字符串的时候,直接用" "
括起来或者用%s
这个占位符进行打印都一样(只限于字符串打印)。那么,什么是占位符呢?别急,现在介绍。 - 占位符的介绍:这玩意儿,从表面就能理解其意思——就是给人家提前占个位置。比如,
printf("Hello World");==printf("%s","Hello World");
前面,咱们已经讲过了字符' '
和字符串" "
的打印(忘了的同学,回前面补习去)。%s
就是一个占位符,是专门用来打印字符串的占位符。 打印不同的信息时,就用对应着不同的占位符。用占位符进行打印的格式:printf("占位符",要打印的信息)
。当打印字符串的时候,不用占位符直接打印和用占位符进行打印是一样的(就像上面举的例子)。只有字符串才可以这样,别的可不行。 进行代码展示:
- printf的打印: 我们在之前有见过它的打印格式。比如,
printf("%d" , 5); //整数占位符,打印整数的
printf("%c" ,' c'); //字符占位符,打印字符的
printf("%c" , '5');
printf("%f" , 5.6); //小数占位符,打印小数的
- C语言中的占位符(黑色加重为常用的):
这里不需要都要记住,目前只需要记住黑色加重的部分,至于其它部分,用的时候查一下就OK。 - 占位符的使用: 我们想打印几个数据就用多少个占位符,还可以混用占位符进行打印信息。如代码所示:
printf("%d %d\n ",5,6);
printf("%d %c\n",5,'a');
printf("%d %s\n",5,"hello world"); //printf函数不会自动换行,所以为了美观,需要我们手动添加换行--\n
运行结果图;
从上面的代码中,我们可以看出来,printf
函数的参数个数比所使用的占位符个数多一。(参数:函数内,每一个逗号就代表一个参数。
)。不知道各位有没有看出来,我们在两个占位符之间加了空格,结果输出就有空格。我们在"占位符"
内,无论样输入空格,结果就跟我们所输入的一模一样,如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
/*printf("%d %d\n ", 5, 6);
printf("%d %c\n", 5, 'a');
printf("%d %s\n", 5, "hello world");*/
printf("%d%d\n ", 5, 6);
printf("%d %d\n ", 5, 6);
return 0;
}
运行结果图:
- printf函数输出数据的宽度限制:不同的占位符限制宽度大同小异。
%d
和%s
的数据宽度限制:在%
和d
之间加上数字,%
和s
之间加上点和数字就进行了限制,比如,%5d ,%.5s
.对于整数和字符串的作用效果不同。对于整数而言,不会限制其输出位数,因为整数本身就是一个整体,限制不了,它的数字代表它的最少位,当数据位数,超过你所写的数字位数时,就啥事没有,正常输出,但当数据位数少于你所写的数字位数时,会对其位数进行补充,直至满足你所写的位数。而字符串就恰恰相反,当字符串超出你所写的数字宽度时,它就输出宽度范围内的,当字符串少于你所写的数字宽度时,它就全部输出。总结:对于整数而言,数字宽度是它的下限。对于字符串而言,数字宽度是它的上限。 进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("-----\n");
printf("%5d\n", 5);
printf("%.3s\n", "-----");
return 0;
}
结果运行图:
不知道大家从结果运行图中有没有看出来,%5d
中,由于咱们的位数不够,所以它就进行补位,但我们能发现,它补的位偏左(从右边对齐,向左进行补位)。这就要讲到一个新的知识点了——那就是在%
和d
之间加上+
和-
,会影响最后,是向左对齐开始补位,还是向右对齐开始补位。加+
或者不加(不加的话,系统默认就是右对齐),就是右对齐,向左开始补齐。反之,加-
就是左对齐,向右开始补齐。如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("%s\n", "------");
printf("%6d\n", 5 ); //右对齐
printf("%-6d\n", 5); //左对齐
return 0;
}
结果运行图:
- %d的符号:我们前面都见过,我们进行打印正整数时,都是打印
5,6,7
这些数字。当然,在我们日常生活中,我们写正整数的时候,也不带+
号(省略不写了),C语言中也是省略不写,我们为了想带个正号时,就可以在%
和d
之间加个+
。这里加不加+
对负数没有影响。 如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("%d\n", 5); // 默认不带+号
printf("%+d\n", 5); // 带了+号
printf("%+d\n", -5); //对负数没有影响
return 0;
}
结果运行图:
%f
的数据宽度控制:有时候我们不需要输出太多的小数位,这个时候就需要进行限位。在%
和f
之间加上.数字
就可以限制小数点后面的位数,然后会四舍五入。比如,%.3f
就是限制小数点后三位,满足四舍五入就近一,不满足就舍弃。如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("%f\n", 5.789); //可以看出来,有限制小数位的作用
printf("%.2f\n", 5.789);
return 0;
}
运行结果图:
我们还可以限制整个小数的位数(这里小数点也算进去),比如,%5.3f
点前面的数字表示限制整个小数的位数(小数点也算哟),点后面就是限制小数点后面的位数。限制小数整体的位数跟%d
的原理一样的(可以参考)-----不够就给你补齐,超了就全部输出。如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("%f\n", 5.789); //可以看出来,有限制小数位的作用
printf("%.2f\n", 5.789);
printf("%10.2f\n", 5.789); //总共10位数据,不够就给你补齐。
return 0;
}
结果运行图:
前面咱们所写的%5d,%.5s,%.6f,%5.6f
,中的数字可以用*
来替代,比如,printf("%5d\n", 5)等价于printf("%*d\n", 5, 5)
。每个*
代表一个数字(参数),所以要在后面补上,即:*===5
。如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
printf("%5d\n", 5);
printf("%*d\n", 5, 5);
printf("%.5s\n", "abcdefgh");
printf("%.*s\n", 5, "abcdefgh"); //每写一个*,就在后面补一个对应的数据(参数)
printf("%.3f\n", 5.4789);
printf("%.*f\n", 3, 5.4789);
printf("%12.3f\n", 5.4789);
printf("%*.*f\n",12, 3, 5.4789);
return 0;
}
运行结果图:
我个人感觉,这样写挺麻烦,不太建议这样写。(根据个人习惯来)
scanf
输入函数 :printf函数是用来输出数据的,有时候我们需要输入数据,就需要用到scanf输入函数。格式:scanf(" 占位符",数据)
。它的输入格式与printf
输出格式很类似。scanf
函数基本用法: 它就是用来给用户输入信息用的,用标准设备进行输入(键盘),标准设备输出(带有屏幕的显示器)。对于scanf函数的理解可以如图所示:
当程序运行到这个函数的时候,程序会在这里停止,当用户输入数据并且按下回车键后,scanf函数就开始读取用户输入的数据,然后程序才继续往下执行。scanf
函数读取数据原理:scanf函数读取数据的本质不是数据,而是这个数据的地址,然后再通过地址找到数据所在的空间,然后进行输入数据。前面,咱们写过这样的代码:int a =10 ;scanf("%d ",&a);
。其中就用了&
取地址操作符。除了数组(数组名就是首地址,所以不需要&
)和指针(指针本身就是地址,所以不需要&
,以后我们会详解的)不需要&
,其它变量(数据)输入就要加&
,进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 10;
char arr[20] = "ab";
scanf("%d", &a); //输入整数
scanf("%s", arr); //输入字符串
printf("%d\n ", a);
printf("%s\n ", arr);
return 0;
}
结果运行图:
scanf
函数数据输入的形象化理解:其时,当我们输入数据的时候,scanf函数是不会立即读取的,所输入的数据会暂时先放入缓存,当我们按下回车键后,scanf函数就会根据占位符,对所输入的数据进行解读(输入)。当我们有多个scanf函数时,第一个scanf函数会先找符合占位符的数据,然后其它scanf函数会依次找符合的数据。形象比喻:缓存就像个有序号格子的大盒子,每次拿就只能按序号来一个一个拿,数据就是放入这个盒子的东西,scanf函数就是对这些东西有不同需求的人(因为占位符不同),scanf函数就要从第一个格子开始拿数据,符合的就拿走,不符合的就空手,到下一个scanf函数时,上一个函数如果符合拿走数据的化,那么本函数就拿走剩下符合的数据,如果上一个函数不符合,那么它就从第一个格子开始拿,去找合适的数据,以此类推。进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{ //输入aaaa20
int a = 10;
char arr[20] = "ab";
scanf("%d", &a); //输入整数
scanf("%s", arr); //输入字符串
printf("%d\n ", a);
printf("%s\n ", arr);
return 0;
}
运行结果图:
当我们输入aaa 20时,第一个scanf函数就会按照格子顺序来解读,由于第一个scanf的占位符是"%d"
,但我们第一个格子放的数据是字符串,所以这个盒子里的东西会原封不动,所以,a的值就不会改变。当第二个scanf函数时,它也要从第一个格子开始读取,由于第一个格子时aaaa。所以,成功读取。所以就会出现这样的结果图。
- scanf函数中常用的占位符;如图所示:
%d, %f,%lf,%Lf
的讲解:这些都是数值占位符。在输入数据时,数值占位符会自动过滤空白字符,比如,空格,制表符(tab键空出的格子),换行符。进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int a = 0;
float b = 0;
scanf("%d %f",&a ,&b);
printf("%d\n%f", a, b);
return 0;
}
结果运行图:
%s
占位符:它会从非空格开始读取数据,遇到空白字符就会结束读取,所以,%s
不适合用来输入句子,书名,歌词等(因为它们会涉及到空白符)。scanf
函数会在成功读取的字符串后面加上\0
。 进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
(
char arr[20];
scanf("%s", arr);
printf("%s ", arr);
return 0;
}
结果运行图:
会发现输入的数据有空格,结果输出就不完善。
scanf
函数具有不安全性:当我们在scanf函数里面输入字符串的时候,它不知道你输入的字符串长度会不会超出你所起初设置的范围,比如,代码所示:
char arr [20]; //我们限制了字符串的长度
scanf("%s" ,arr); //假如,我们输入的字符串长度超出了范围,它也会给你全部输出,这就超出了你原本的意愿。
printf("%s ",arr); //所以,scanf函数不安全
进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char arr[20]; //输入30个a时
scanf("%s", arr);
printf("%s ", arr);
return 0;
}
运行结果图:
它会报错,但也能输出全部数据。为了防止这种情况发生(为了限制输入位数),我们有一个写法——%[数字]s
,在其中间加上数字。比如,%5s
无论你输入多长的字符串,到最后它就只读取5位,比如,代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{ //输入30个a
char arr[20];
scanf("%5s", arr);
printf("%s ", arr);
return 0;
}
结果运行图:
%c
的介绍:前面,我们讲过数值占位符会过滤掉空白符。但%c
不会,因为空白符它本身也是字符,而%c
恰恰也就是输入字符的,所以开头你给空白符它也会读取的,进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char arr =0;
scanf("%c", &arr);
printf("%c", arr);
return 0;
}
结果运行图:
为了跳过前面的空白字符,我们可以在%c
之前加上空格,它就会跳过起首空白字符,比如, " %c"
,如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
char arr =0;
scanf(" %c", &arr); //加了空格
printf("%c", arr);
return 0;
}
结果运行图:
%*c
赋值忽略符:有时候,我们的用户输入的信息可能不与格式相同,从而导致结果输出不准确,比如代码所示:
//以本次输入年,月,日信息的代码为例子。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
(
int year = 0;
int month = 0;
int day = 0;
int c =scanf("%d-%d-%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
return 0;
}
在scanf
函数输入特殊信息时(比如2024/1/24,2024-1-24
这样的信息格式),那么我们在在占位符中就要写成相应的格式,比如代码所示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
int c =scanf("%d-%d-%d", &year, &month, &day); //输入2024-1-24
printf("%d-%d-%d\n", year, month, day); //为了让输出格式好看,我们也要加上
return 0;
}
结果运行图:
对于其它输入格式,大家可自行试试。我们想让用户按照咱们的格式输入,但有时候就事与愿违。为了这种情况的发生,我们用赋值忽略符,它会忽略我们所输入的字符格式,如代码所示;
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
int c =scanf("%d%*c%d%*c%d", &year, &month, &day);
printf("%d-%d-%d\n", year, month, day);
//printf("scanf函数的返回值:%d",c);
return 0;
}
结果运行图:
scanf
函数的返回值:scanf
函数是有返回值的,而且返回值类型为整数。它返回的是成功读取数据的个数,进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
int year = 0;
int month = 0;
int day = 0;
int c =scanf("%d%d%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
printf("scanf函数的返回值:%d",c);
return 0;
}
结果运行图:
scanf
函数在成功读取数据前,如果发生读取数据错误或者读取到文件末尾,它就会返回EOF(数值为-1)
,EOF=end of file(文件结束标志)。在VS2022进行演示这个现象,需要输入3次ctrl+Z
,这是VS2022中的一个bug。但在其它编译器其中(比如,DEVc++),输入一次ctrl+z
就OK了。进行代码展示:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{ /
int year = 0;
int month = 0;
int day = 0;
int c =scanf("%d%d%d", &year, &month, &day);
printf("%d %d %d\n", year, month, day);
printf("scanf函数的返回值:%d",c);
return 0;
}
结果运行图:
彩蛋放松一下!!!
听会儿音乐放松一下吧!!!
https://www.bilibili.com/video/BV1mN4y1Y7Ve/?spm_id_from=333.337.search-card.all.click&vd_source=7d0d6d43e38f977d947fffdf92c1dfad
每章一句:“纵有疾风起,人生不言弃。风乍起,合当奋意向此生。”
感谢你能看到这里,点赞+关注+收藏是对我最大的鼓励,咱们下期见!!!